Mozilla声称不久前(〜2008)会删除__proto__,并且仍在浏览器中。它仍然会被弃用吗?它也可以在Opera,(我认为是Safari)和Chrome中运行。我不需要担心IE,所以我希望继续使用它。
但是,我不希望我的代码在一天后停止工作,所以继续我的问题:
__proto__允许简单的继承:
a.__proto__ = {'a':'test'}
无论如何,我可以用符合标准的方式复制它吗?我知道函数继承很丑陋,这使我只想创建一个原型(prototype)链的事实变得过于复杂。只是想知道是否有向导解决了这个问题。
谢谢
最佳答案
注意:更改 __proto__
的值被认为是不好的做法。 JavaScript的创建者Brendan Eich强烈不建议这样做。实际上, __proto__
属性已经从Rhino等少数JavaScript引擎中完全删除。如果您想知道为什么,请阅读Brendan Eich的following comment。
更新:浏览器不会删除 __proto__
属性。实际上,ECMAScript Harmony现在已经标准化了 __proto__
属性和 setPrototypeOf
函数。仅出于传统原因才支持 __proto__
属性。强烈建议您使用 setPrototypeOf
和 getPrototypeOf
代替 __proto__
。
警告:尽管 setPrototypeOf
现在是一个标准,但仍然不鼓励您使用它,因为对对象原型(prototype)进行更改总是会导致优化工作中断并使代码运行缓慢。另外, setPrototypeOf
的使用通常表示质量低劣的代码。
您不必担心您现有的代码一天不会工作。 __proto__
属性在这里停留。
现在,对于眼前的问题。我们希望以符合标准的方式执行类似的操作:
var a = {
b: "ok"
};
a.__proto__ = {
a: "test"
};
alert(a.a); // alerts test
alert(a.b); // alerts ok
显然,由于我们没有创建新的对象,因此您不能使用
Object.create
来达到此目的。我们只是试图更改给定对象的内部[[proto]]
属性。问题在于,一旦创建了对象,就无法更改其内部[[proto]]
属性(通过使用我们试图避免的__proto__
除外)。因此,为了解决此问题,我编写了一个简单的函数(请注意,该函数适用于除函数之外的所有对象):
function setPrototypeOf(obj, proto) {
var result = Object.create(proto);
var names = Object.getOwnPropertyNames(obj);
var getProp = Object.getOwnPropertyDescriptor;
var setProp = Object.defineProperty;
var length = names.length;
var index = 0;
while (index < length) {
var name = names[index++];
setProp(result, name, getProp(obj, name));
}
return result;
}
因此,我们现在可以按如下所示更改任何对象的原型(prototype)(请注意,我们实际上并不是在更改对象的内部
[[proto]]
属性,而是创建一个与给定对象具有相同属性并继承自给定对象的新对象原型(prototype)):var a = {
b: "ok"
};
a = setPrototypeOf(a, {
a: "test"
});
alert(a.a); // alerts test
alert(a.b); // alerts ok
<script>
function setPrototypeOf(obj, proto) {
var result = Object.create(proto);
var names = Object.getOwnPropertyNames(obj);
var getProp = Object.getOwnPropertyDescriptor;
var setProp = Object.defineProperty;
var length = names.length;
var index = 0;
while (index < length) {
var name = names[index++];
setProp(result, name, getProp(obj, name));
}
return result;
}
</script>
简单有效(我们没有使用
__proto__
属性)。