关于javascript:函数对象__proto__和prototype属性

Function object __proto__ and prototype property

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

1
2
3
4
5
6
7
8
function Animal(voice)
 {
  this.voice = voice|| 'meaw'
  }

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

我知道动物函数有一个原型属性,指向它的原型对象。它的原型对象有指向后面的构造函数和指向对象对象原型的原型属性

我知道每个函数对象都继承自函数的对象原型,并且继承自对象的对象原型,包括uu proto_uuuu属性。现在,当我进一步研究它的时候,我发现函数的对象原型和属性链接到同一个原型对象。

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

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

1
2
3
4
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的对象。那么让我们把Animal的东西放下,用Function.prototype重复你的方程:

1
2
Function.prototype.constructor.__proto__ == Function.prototype.constructor.prototype // true
Function.prototype.constructor.__proto__ == Function.prototype // true

现在,Function.prototype.constructor属性(与所有定义良好的原型对象一样)指向其各自的构造函数Function构造函数函数。所以我们得到了

1
2
Function.__proto__ == Function.prototype // true
Function.__proto__ == Function.prototype // true

现在,考虑到Function是一个函数,它从Function.prototype继承就像所有其他函数一样是有意义的。

这就是你的测试所证实的,就像你基本上所做的那样。

1
2
3
4
Function.__proto__.test = 28;

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

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


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

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

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

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

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

16

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

Function构造函数[[Prototype]](a.k.a Function.__proto__在规范中定义如下:

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).

Function.prototype房地产价值相同:

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

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

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


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

您正在混合"原型属性"和"原型对象"。

.prototype是构造函数函数的一个属性。无论何时调用构造函数,它都会创建原型对象设置为Constructor.prototype的对象。

1
2
3
function Animal(){}
let animal = new Animal();
animal.__proto__ = Animal.prototype;

实际上,__proto__属性只是在Object.prototype上定义的getter,它称为Object.getPrototypeOf

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

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

这就是JavaScript查找链的工作原理。

首先注意到

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

因为对于任何函数A

4

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

1
Function.__proto__ === Function.prototype \\true

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

通常,当a = new A();

1
a.__proto__ === A.prototype \\true

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

1
Function.constructor === Function //true

现在更有意义了。

现在我们回顾一下这个问题。

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

等同于:

1
Function.__proto__.test = 28;

等同于:

1
Function.prototype.test = 28;

因此,现在很明显,这两个console.log打印出了相同的文件,因为:

1
Animal.__proto__ === Function.prototype \\ture

就像我们刚开始说的。