【问题标题】:Relation between [[Prototype]] and prototype in JavaScriptJavaScript 中 [[Prototype]] 与原型的关系
【发布时间】:2010-09-27 20:18:53
【问题描述】:

来自http://www.jibbering.com/faq/faq_notes/closures.html

注意:ECMAScript 定义了内部 Object 类型的内部 [[prototype]] 属性。此属性不能直接通过脚本访问,但它是在属性访问器解析中使用的内部 [[prototype]] 属性引用的对象链;对象的原型链。存在一个公共原型属性以允许与内部 [[prototype]] 属性关联的原型的分配、定义和操作。 两者之间的关系细节在 ECMA 262(第 3 版)中有描述,超出了本次讨论的范围。

两者之间的关系细节是什么?我浏览了 ECMA 262,我读到的都是这样的:

构造函数的关联原型可以被程序表达式constructor.prototype引用,

原生 ECMAScript 对象有一个称为 [[Prototype]] 的内部属性。此属性的值为 null 或对象,用于实现继承。

每个内置函数和每个内置构造函数都有 Function 原型对象,它是表达式 Function.prototype 的初始值

每个内置原型对象都有Object原型对象,它是表达式的初始值 Object.prototype (15.3.2.1),作为其内部 [[Prototype]] 属性的值,除了 Object 原型对象本身。

据我所知,对于几乎任何对象,[[Prototype]] 属性都等效于prototype 属性。我弄错了吗?

【问题讨论】:

    标签: javascript ecma262


    【解决方案1】:

    我相信你在大多数情况下是对的。

    每个对象都有一个隐藏的[[Prototype]] 属性,用于继承。函数还有一个公共的prototype 属性,仅在函数用作构造函数时使用:当使用new 构造对象时,新对象的[[Prototype]] 属性设置为prototype 属性用作构造函数的函数。

    例如

    function C() {}
    C.prototype = P1;  
    var obj = new C();  // obj.[[Prototype]] is now P1.
    

    您可以使用Object.getPrototypeOf(<obj>) 获取[[Prototype]] 属性。 (此方法在 ECMAScript 5 中指定。旧版本的 JavaScript 没有任何标准的读取 [[Prototype]] 的方式。

    您可以通常通过构造函数获取原型,例如:

    obj.constructor.prototype == Object.getPrototypeOf(obj) 
    

    但并非总是如此,因为构造函数的原型属性可以重新赋值,但对象的[[Prototype]]在对象创建后无法重新赋值。所以如果你这样做:

    C.prototype = P2;
    

    然后

    obj.constructor.prototype != Object.getPrototypeOf(obj)
    

    因为C的原型现在是P2,但是obj[[Prototype]]仍然是P1

    请注意,只有 函数具有 prototype 属性。另请注意,函数的prototype 属性与函数的[[Prototype]] 属性不同!

    【讨论】:

    • 正是我想要的。感谢您非常明确的回答!我已经“弄清楚”了所有这些,但并没有把它具体化。
    • 这是一个很好的答案,帮助我理解了继承,尽管它确实在 mozilla 网站上说 proto 属性可以在初始构建后更改为指向不同的对象。 developer.mozilla.org/en/Core_JavaScript_1.5_Reference/…
    • 补充一点:我相信在 Firefox 中你可以访问 [[Prototype]]__proto__
    【解决方案2】:

    除了 olavk 的回答:一些 JavaScript 实现(例如mozilla's)允许直接访问 [[Prototype]] 属性...

    【讨论】:

      【解决方案3】:

      直接回答您的问题:从逻辑上讲,它是对象的构造函数 prototype 属性的私有副本。使用元语言这是创建对象的方式:

      // not real JS
      
      var Ctr = function(...){...};
      Ctr.prototype = {...}; // some object with methods and properties
      
      // the object creation sequence: var x = new Ctr(a, b, c);
      var x = {};
      x["[[prototype]]"] = Ctr.prototype;
      var result = Ctr.call(x, a, b, c);
      if(typeof result == "object"){ x = result; }
      // our x is fully constructed and initialized at this point
      

      此时我们可以对原型进行修改,修改会反映到类的所有对象上,因为它们是通过引用来引用原型的:

      Ctr.prototype.log = function(){ console.log("...logging..."); };
      
      x.log();  // ...logging..
      

      但是如果我们在构造函数上改变原型,已经创建的对象会继续引用旧对象:

      Ctr.prototype = {life: 42};
      // let's assume that the old prototype didn't define "life"
      
      console.log(x.life);  // undefined
      x.log();              // ...logging...
      

      完全按照标准[[prototype]]是不可用的,但是Mozilla用__proto__属性(只读)扩展了标准,这暴露了通常隐藏的[[prototype]]

      同样,__proto__ 可以在 the next ES3.1 standard 中合法化。

      【讨论】:

      • Hmm.. 他们没有标准化 proto,而是创建了 Object.getPrototypeOf(target),它将返回 target.[[Prototype]]。主要区别在于您不能分配给结果。
      猜你喜欢
      • 2013-08-08
      • 1970-01-01
      • 2014-02-07
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 2021-11-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多