更新: ES6 现在指定Object.setPrototypeOf(object,prototype)
.
2012 年 2 月编辑:下面的答案不再准确。proto被添加到 ECMAScript 6 作为“规范可选”,这意味着它不需要被实现,但如果它被实现,它必须遵循给定的规则集。这目前尚未解决,但至少它将正式成为 JavaScript 规范的一部分。
这个问题比表面上看起来要复杂得多,而且超出了大多数人对 Javascript 内部知识的了解。
在prototype
创建该对象的新的子对象时,对象的属性使用。改变它并不反映在对象本身,而是反映在该对象被用作其他对象的构造函数时,并且对改变现有对象的原型没有用处。
function myFactory(){};
myFactory.prototype = someOtherObject;
var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true
对象具有指向当前原型的内部 [[prototype]] 属性。它的工作方式是,无论何时调用对象上的属性,它都会从该对象开始,然后向上遍历 [[prototype]] 链,直到在根对象原型之后找到匹配项或失败。这就是 Javascript 允许运行时构建和修改对象的方式;它有一个寻找它需要的东西的计划。
该__proto__
属性存在于某些实现中(现在很多):任何 Mozilla 实现,我所知道的所有 webkit 实现,以及其他一些实现。此属性指向内部 [[prototype]] 属性,并允许在创建后修改对象。由于这种链式查找,任何属性和函数都会立即切换到匹配原型。
此功能虽然现在已标准化,但仍然不是 JavaScript 的必需部分,并且在支持它的语言中,很有可能将您的代码归入“未优化”类别。JS 引擎必须尽最大努力对代码进行分类,尤其是经常访问的“热”代码,如果你在做一些花哨的事情,比如修改__proto__
,他们根本不会优化你的代码。
这篇文章https://bugzilla.mozilla.org/show_bug.cgi?id=607863专门讨论了它们的当前实现__proto__
和它们之间的差异。每个实现的做法都不一样,因为这是一个难以解决的问题。Javascript 中的一切都是可变的,除了 a.) 语法 b.) 宿主对象(DOM 技术上存在于 Javascript 之外)和 c.) __proto__
。其余的完全掌握在您和其他所有开发人员的手中,因此您可以明白为什么会__proto__
像拇指酸痛一样伸出来。
有一件事__proto__
允许这样做,否则是不可能做到的:在运行时指定对象原型与其构造函数分开。这是一个重要的用例,也是__proto__
尚未消亡的主要原因之一。重要的是,它已经成为 Harmony 制定中的一个严肃讨论点,或者很快就会被称为 ECMAScript 6。在创建过程中指定对象原型的能力将成为下一版 Javascript 的一部分,这将是指示__proto__
天数的钟是正式编号的。
在短期内,__proto__
如果您的目标是支持它的浏览器(不是 IE,而且 IE 永远不会),则可以使用。由于 ES6 直到 2013 年才会最终确定,因此它很可能会在未来 10 年在 webkit 和 moz 中运行。
Brendan Eich - re:ES5 中新对象方法的方法:
抱歉,...但是 settable __proto__
,除了对象初始化器用例(即,在一个新的对象还不能到达,类似于 ES5 的 Object.create 上),是一个糟糕的主意。我写这篇文章是__proto__
在 12 年前设计和实现了可设置的。
...缺乏分层是一个问题(考虑带有键的 JSON 数据"__proto__"
)。更糟糕的是,可变性意味着实现必须检查循环原型链以避免 ilooping。[需要不断检查无限递归]
最后,__proto__
对现有对象进行变异可能会破坏新原型对象中的非泛型方法,这不可能在__proto__
正在设置的接收者(直接)对象上工作。一般来说,这只是一种糟糕的做法,是一种有意的类型混淆。