函数对象 __proto__ 和原型 属性

Function object __proto__ and prototype property

我正在尝试找出我编写的函数的原型链

function Animal(voice)
 {
  this.voice = voice|| 'meaw'
  }

  Animal.prototype.speak =function() {
  console.log(this.voice);
  }

我知道 Animal 函数有一个原型 属性 指向它的原型对象。它的原型对象具有指向后方的构造函数和 __proto__ 属性 指向对象对象原型

我知道每个函数对象都继承自 Function 的对象 prototype 并且继承自 Object 的对象 原型包括__proto__属性。现在,当我进一步调查它时,我发现 Function 的 对象 prototype__proto__ 属性 链接到同一个原型对象。

console.log(Animal.__proto__.constructor.__proto__  == Animal.__proto__.constructor.prototype ); //true
console.log(Animal.__proto__.constructor.__proto__ == Animal.__proto__); //true

然后我做了一些进一步的测试来证明它

Animal.__proto__.constructor.__proto__.test = 28;

console.log(Animal.__proto__.constructor.__proto__.test); // prints 28
console.log(Animal.__proto__.test);  //prints 28

也就是说它的原型和它继承的原型是一样的。有什么理由这样设置的吗?

您已经知道 Object.getPrototypeOf(Animal)(或 Animal.__proto__)是 Function.prototype object。所以让我们放弃那个 Animal 的东西,然后用 Function.prototype:

重复你的方程式
Function.prototype.constructor.__proto__ == Function.prototype.constructor.prototype // true
Function.prototype.constructor.__proto__ == Function.prototype // true

现在,Function.prototype.constructor 属性(就像所有定义明确的原型对象一样)指向其各自的构造函数 Function constructor function。所以我们有

Function.__proto__ == Function.prototype // true
Function.__proto__ == Function.prototype // true

现在,鉴于 Function 是一个函数,只有它像所有其他函数一样从 Function.prototype 继承才有意义。

这就是你的测试所证实的,基本上你就是这么做的

Function.__proto__.test = 28;

Function.__proto__.test // 28
Function.prototype.test // 28

是的,Function.testAnimal.test 现在也会产生 28

这就是 Javascript 查找链的工作方式。

首先注意

Animal.__proto__ === Function.prototype \true
Animal.__proto__.constructor === Function \true

因为对于任何函数 A

A.prototype.constructor === A   

那么问题就变成了,Function__proto__属性是什么?是 Function.prototype.

Function.__proto__ === Function.prototype \true

这有点奇怪,因为这两个属性通常不相同。

通常,当 a = new A();

a.__proto__ === A.prototype \true

实例的 __proto__ 属性 等于其构造函数的 prototype; 但是考虑到每个函数都是 Function 的实例并且 Function 本身也是一个函数。 Function是自身的构造函数!

Function.constructor === Function //true

现在更有意义了。


现在我们回过头来看问题

Animal.__proto__.constructor.__proto__.test = 28;

等同于:

Function.__proto__.test = 28;   

等同于:

Function.prototype.test = 28; 

所以现在很清楚两个console.log打印出来的是一样的因为:

Animal.__proto__ === Function.prototype \ture

正如我们一开始所说的。

I found out that Function's object prototype and proto property links to the same prototype object.

您正在混合 "prototype property" 和 "prototype object"。

.prototype 是构造函数上的 属性。每当调用构造函数时,它都会创建 原型对象 设置为 Constructor.prototype.

的对象
function Animal(){}
let animal = new Animal();
animal.__proto__ = Animal.prototype;

事实上,__proto__ 属性 只是在 Object.prototype 上定义的 getter 调用 Object.getPrototypeOf.

您的困惑是由于 Object.getPrototypeOf(Animal) === Function.prototype(所有函数都是 Function 的实例)和函数 constructor/prototype 被扭曲造成的。

Function.prototype === Function.__proto__; // true
typeof Function.prototype; // "function"

Animal 是一个函数,与所有函数一样(除非您修改它),它链接回 Function.prototype 对象。所以:

Animal.__proto__ === Function.prototype //true

现在,如果我们将 Animal.__proto__ 替换为 Function.prototype,我们将得到:

Function.prototype.constructor.__proto__ === Function.prototype

这是为什么? Function.prototype.constructor 链接回其构造函数,即 Function 构造函数。所以这实际上意味着:

Function.__proto__ === Function.prototype

如果您想知道为什么 Function.__proto__Function.prototype 共享相同的值,请查看规范。

The Function constructor [[Prototype]] (a.k.a Function.__proto__) is defined as follows in the specification:

The Function constructor is itself a built-in function object. The value of the [[Prototype]] internal slot of the Function constructor is %FunctionPrototype%, the intrinsic Function prototype object (19.2.3).

The Function.prototype property shares the same value:

The value of Function.prototype is %FunctionPrototype%, the intrinsic Function prototype object (19.2.3).

因此,由于 Functionnew Function() 的结果都是函数,因此它们共享相同的 [[Prototype]]:

var func = new Function()
Function.__proto__ === func.__proto__