【问题标题】:Function object __proto__ and prototype property函数对象 __proto__ 和原型属性
【发布时间】:2016-05-22 10:34:39
【问题描述】:

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

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

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

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

我知道每个函数对象都继承自 Function 的对象 prototype 并继承自 Object 的对象 prototype,包括 __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

这意味着它的原型和从它继承的原型是相同的。有什么理由这样设置吗?

【问题讨论】:

    标签: javascript javascript-objects


    【解决方案1】:

    您已经知道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

    【讨论】:

    • 好吧,这是有道理的。但是你不认为 Object 也应该是真的,因为它也是一个对象但是 Object.prototype == Object.__proto__ 是假的
    • Object 构造函数同时也是instanceof Object,首先是一个函数和Object.prototypeOf(Object) == Function.prototypeFunction 是唯一一个其内部 [[prototype]](继承链接)指向与其 .prototype 属性相同的对象的内置对象。
    【解决方案2】:

    这就是 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
    

    正如我们一开始所说的。

    【讨论】:

    • 谢谢 Quarter2Twelve。你也解释的很好!
    【解决方案3】:

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

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

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

    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:

    Function 构造函数本身就是一个内置函数对象。这 Function 构造函数的 [[Prototype]] 内部槽的值 是 %FunctionPrototype%,内在的 Function 原型对象 (19.2.3)。

    The Function.prototype property shares the same value:

    Function.prototype 的值为 %FunctionPrototype%,内在 函数原型对象 (19.2.3)。

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

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

    【讨论】:

    • 感谢 nils 提供规范参考!
    【解决方案4】:

    我发现 Function 的对象原型和 proto 属性链接到同一个原型对象。

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

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

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

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-07
      • 2015-12-24
      • 1970-01-01
      • 2014-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多