javascript - 如何设置一个已经实例化的JavaScript对象的原型(prototype)?

标签 javascript function-prototypes

假设我有一个对象 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/

相关文章:

javascript - 如何找出哪个包使用了不安全的 componentWillMount 方法?

javascript - 使用 jQuery 将 JSON 对象发布到 Spring 3 Controller

javascript - Node.js:events.EventEmitter.call(this)与Obj.prototype.__proto__ = events.EventEmitter.prototype的关系;

Perl 函数原型(prototype)

c++ - 在该命名空间中的另一个函数内向前声明一个命名空间中的函数

javascript - 如何在 javascript 中使用正则表达式来匹配数字和符号?

javascript - e.preventDefault 不阻止提交

javascript - CORS访问阻止

c - 为什么我的用户定义数组的平均值不正确? C

c - 如何在 C 中接收未命名的结构作为函数参数?