假设我有一个对象 foo
在我的 JavaScript 代码中。 foo
是一个复杂的对象,它是在其他地方生成的。如何更改 foo
的原型(prototype)对象?
我的动机是为从 .NET 序列化为 JavaScript 文本的对象设置适当的原型(prototype)。
假设我在 ASP.NET 页面中编写了以下 JavaScript 代码。
var foo = <%=MyData %>;
假设MyData
是调用 .NET JavaScriptSerializer
的结果在 Dictionary<string,string>
上对象。
在运行时,这变成如下:
var foo = [{"A":"1","B":"2"},{"X":"7","Y":"8"}];
如您所见,foo
变成一个对象数组。我希望能够初始化 foo
具有适当的原型(prototype)。我不想修改 Object.prototype
也不Array.prototype
.我该怎么做?
最佳答案
更新 ES6 现在指定Object.setPrototypeOf(object, prototype)
.
2012 年 2 月编辑:下面的答案不再准确。 proto 被添加到 ECMAScript 6 作为“规范可选”,这意味着它不需要被实现,但如果是,它必须遵循给定的规则集。这目前尚未解决,但至少它将正式成为 JavaScript 规范的一部分。
这个问题比表面上看起来要复杂得多,而且在 Javascript 内部知识方面超出了大多数人的薪水等级。
对象的 prototype
属性在创建该对象的新子对象时使用。更改它不会反射(reflect)在对象本身,而是在该对象用作其他对象的构造函数时反射(reflect)出来,并且对更改现有对象的原型(prototype)没有用。
function myFactory(){};
myFactory.prototype = someOtherObject;
var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true
对象有一个指向当前原型(prototype)的内部 [[prototype]] 属性。它的工作方式是,无论何时调用对象的属性,它都会从对象开始,然后向上遍历 [[prototype]] 链,直到在根对象原型(prototype)之后找到匹配项或失败。这就是 Javascript 允许运行时构建和修改对象的方式;它有一个搜索所需内容的计划。
__proto__
属性存在于某些实现中(现在很多):任何 Mozilla 实现,我所知道的所有 webkit 实现,还有一些。此属性指向内部 [[prototype]] 属性,并允许在对象创建后进行修改。由于这种链式查找,任何属性和函数都将立即切换以匹配原型(prototype)。
此功能虽然现在已标准化,但仍然不是 JavaScript 的必需部分,并且在支持它的语言中很可能将您的代码归入“未优化”类别。 JS 引擎必须尽力对代码进行分类,尤其是经常访问的“热”代码,如果你正在做一些花哨的事情,比如修改 __proto__
,他们根本不会优化你的代码.
此帖https://bugzilla.mozilla.org/show_bug.cgi?id=607863专门讨论了__proto__
的当前实现以及它们之间的区别。每个实现方式都不同,因为这是一个难以解决的问题。 Javascript 中的所有内容都是可变的,除了 a.) 语法 b.) 宿主对象(从技术上讲,DOM 存在于 Javascript 之外)和 c.) __proto__
。剩下的就完全掌握在你和其他所有开发人员的手中,所以你可以明白为什么 __proto__
如此突出。
__proto__
允许做一件事,否则不可能做到:在运行时指定对象原型(prototype)与其构造函数分开。这是一个重要的用例,也是 __proto__
尚未消亡的主要原因之一。它已经成为 Harmony 或即将被称为 ECMAScript 6 的一个严肃的讨论点,这一点非常重要。在创建过程中指定对象原型(prototype)的能力将成为下一版本 Javascript 的一部分,这将是指示 __proto__
的日子已正式编号的钟声。
短期内,如果您的目标浏览器支持它(不是 IE,而且永远不会有 IE),您可以使用 __proto__
。它很可能在未来 10 年内在 webkit 和 moz 中运行,因为 ES6 要到 2013 年才能最终确定。
Brendan Eich - 回复:Approach of new Object methods in ES5 :
Sorry, ... but settable
__proto__
, apart from the object initialiser use case (i.e., on a new object not yet reachable, analogous to ES5's Object.create), is a terrible idea. I write this having designed and implemented settable__proto__
over 12 years ago.... the lack of stratification is a problem (consider JSON data with a key
"__proto__"
). And worse, the mutability means implementations must check for cyclic prototype chains in order to avoid ilooping. [constant checks for infinite recursion are required]Finally, mutating
__proto__
on an existing object may break non-generic methods in the new prototype object, which cannot possibly work on the receiver (direct) object whose__proto__
is being set. This is simply bad practice, a form of intentional type confusion, in general.
关于javascript - 如何设置一个已经实例化的JavaScript对象的原型(prototype)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7015693/