如何设置已经实例化的JavaScript对象的原型? [英] How to set the prototype of a JavaScript object that has already been instantiated?

查看:127
本文介绍了如何设置已经实例化的JavaScript对象的原型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我的JavaScript代码中有一个对象 foo foo 是一个复杂的对象,它是在其他地方生成的。如何更改 foo 对象的原型?

Suppose I have an object foo in my JavaScript code. foo is a complex object and it is generated somewhere else. How can I change the prototype of the foo object?

我的动机是将相应的原型设置为序列化的对象。 NET到JavaScript文字。

My motivation is setting appropriate prototypes to objects serialized from .NET to JavaScript literals.

假设我在ASP.NET页面中编写了以下JavaScript代码。

Suppose that I've written the following JavaScript code within an ASP.NET page.

var foo = <%=MyData %>;

假设 MyData 是调用的结果字典上的.NET JavaScriptSerializer < string,string> object。

Suppose that MyData is the result of invoking the .NET JavaScriptSerializer on a Dictionary<string,string> object.

在运行时,这将成为以下内容:

At run-time, this becomes the following:

var foo = [{"A":"1","B":"2"},{"X":"7","Y":"8"}];

如你所见, foo 成为一个对象数组。我希望能够使用适当的原型初始化 foo 。我想要修改 Object.prototype Array.prototype 。我怎么能这样做?

As you can see, foo becomes an array of objects. I would like to be able to initialize foo with an appropriate prototype. I do not want to modify the Object.prototype nor Array.prototype. How can I do this?

推荐答案

编辑2012年2月:以下答案不再准确。 __proto__作为规范可选添加到ECMAScript 6中,这意味着它不需要实现,但如果是,则必须遵循给定的规则集。这个问题目前尚未解决,但至少它将成为JavaScript规范的正式部分。

这个问题比表面看起来要复杂得多,而且超出大多数人对Javascript内部知识的工资等级。

This question is a lot more complicated than it seems on the surface, and beyond most peoples' pay grade in regards to knowledge of Javascript internals.

使用对象的原型属性在创建该对象的新子对象时。更改它不会反映在对象本身中,而是在该对象用作其他对象的构造函数时反映出来,并且无法用于更改现有对象的原型。

The prototype property of an object is used when creating new child objects of that object. Changing it does not reflect in the object itself, rather is reflected when that object is used as a constructor for other objects, and has no use in changing the prototype of an existing object.

function myFactory(){};
myFactory.prototype = someOtherObject;

var newChild = new myFactory;
newChild.__proto__ === myFactory.prototype === someOtherObject; //true

对象有一个内部[[prototype]]属性,指向当前原型。它的工作方式是每当调用一个对象上的属性时,它将从该对象开始,然后通过[[prototype]]链向上,直到它找到匹配,或者在根对象原型之后失败。这就是Javascript允许运行时构建和修改对象的方式;它有一个搜索它需要的计划。

Objects have an internal [[prototype]] property which points to the current prototype. The way it works is whenever a property on an object is called it will start at the object and then go up through the [[prototype]] chain until it finds a match, or fail, after the root Object prototype. This is how Javascript allows for runtime building and modification of objects; it has a plan for searching for what it needs.

某些实现中存在 __ proto __ 属性(现在很多) ):任何Mozilla实现,我所知道的所有webkit,以及其他一些。此属性指向内部[[prototype]]属性,并允许在对象上创建后创建。由于这种链式查找,任何属性和函数都会立即切换到匹配原型。

The __proto__ property exists in some implementations (a lot now): any Mozilla implementation, all the webkit ones I know of, some others. This property points to the internal [[prototype]] property and allows modification post-creation on objects. Any properties and functions will instantly switch to match the prototype due to this chained lookup.

此功能虽然现已标准化,但仍然不是JavaScript的必需部分,并且在支持它的语言中很有可能将您的代码敲入未优化类别。 JS引擎必须尽最大努力对代码进行分类,特别是经常访问的热门代码,如果你正在做一些像修改 __ proto __ 这样的东西,他们就赢了t优化你的代码。

This feature, while being standardized now, still is not a required part of JavaScript, and in languages supporting it has a high likelihood of knocking your code down into the "unoptimized" category. JS engines have to do their best to classify code, especially "hot" code which is accessed very often, and if you're doing something fancy like modifying __proto__, they won't optimize your code at all.

这篇帖子 https://bugzilla.mozilla.org/show_bug.cgi?id=607863 专门讨论了 __ proto __ 的当前实现以及它们之间的差异。每个实现都以不同的方式执行,因为它是一个困难且未解决的问题。 Javascript中的所有内容都是可变的,除了a。)语法b。)主机对象(DOM在技术上存在于Javascript之外)和c。) __ proto __ 。其余的完全由你和其他开发人员掌握,所以你可以看到为什么 __ proto __ 像拇指一样伸出来。

This posts https://bugzilla.mozilla.org/show_bug.cgi?id=607863 specifically discusses current implementations of __proto__ and the differences between them. Every implementation does it differently, because it's a hard and unsolved problem. Everything in Javascript is mutable, except a.) the syntax b.) host objects (the DOM exists outside Javascript technically) and c.) __proto__. The rest is completely in the hands of you and every other developer, so you can see why __proto__ sticks out like a sore thumb.

有一件事 __ proto __ 允许这样做是不可能的:指定一个对象原型在运行时与其构造函数分开。这是一个重要的用例,并且是 __ proto __ 尚未死亡的主要原因之一。重要的是它在Harmony的制定中是一个严肃的讨论点,或者很快被称为ECMAScript 6.在创建过程中指定对象原型的能力将成为下一版Javascript的一部分,这将是表示 __ proto __ 的铃声正式编号。

There is one thing that __proto__ allows for that is otherwise impossible to do: the designation of an objects prototype at runtime separate from its constructor. This is an important use case and is one of the primary reasons __proto__ isn't already dead. It's important enough that it's been a serious discussion point in the formulation of Harmony, or soon to be known as ECMAScript 6. The ability to specify the prototype of an object during creation will be a part of the next version of Javascript and this will be the bell indicating __proto__'s days are formally numbered.

短期内,您可以使用 __ proto __ 如果您的目标是支持它的浏览器(不是IE,也不会是IE)。由于ES6将在2013年之前完成,因此它可能会在未来10年内在webkit和moz中运行。

In the short term, you can use __proto__ if you're targeting browsers that support it (not IE, and no IE ever will). It's likely it'll work in webkit and moz for the next 10 years as ES6 won't be finalized until 2013.

Brendan Eich - re: ES5中新对象方法的方法


抱歉,...但可设置 __ proto __ ,除了使用对象初始化程序case(即,在一个尚未到达的新对象上,类似于ES5的Object.create),是一个糟糕的主意。我在12年前设计并实现了可设置的 __ proto __ 来写这个。

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.

...缺乏分层是一个问题(考虑使用密钥__ proto __的JSON数据)。更糟糕的是,可变性意味着实现必须检查循环原型链以避免ilooping。 [需要对无限递归进行常量检查]

... 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]

最后,改变 __ proto __ 现有对象可能会破坏新原型对象中的非泛型方法,这些方法无法在正在设置 __ proto __ 的接收方(直接)对象上工作。这通常是一种不好的做法,一种故意类型混淆的形式。

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对象的原型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆