注意:改變__proto__
的值是不好的做法。這種做法受到JavaScript創始人Brendan Eich等人的強烈譴責。事實上__proto__
屬性已經完全從像Rhino這樣的幾個JavaScript引擎中刪除。如果您想知道爲什麼然後閱讀Brendan Eich的following comment。
更新:瀏覽器不會刪除__proto__
屬性。實際上,ECMAScript Harmony現在已對__proto__
屬性和setPrototypeOf
函數進行了標準化。 __proto__
屬性僅受傳統原因支持。強烈建議您使用setPrototypeOf
和getPrototypeOf
而不是__proto__
。
警告:雖然setPrototypeOf
現在是一個標準,你仍然從因爲變異的對象的原型總是殺死優化,使你的代碼慢用它氣餒。另外,使用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;
}
所以我們現在可以更改任何對象的原型創建完畢後,如下所示(注意,我們實際上並沒有改變對象的內部[[proto]]
屬性,而是創建一個新的對象具有相同的屬性定對象從給定的原型繼承):
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__
屬性)。
看起來'__proto__'可能在下一個ECMAScript中被標準化。直到最終確定後才能完全確定。 http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts ...至少在附件B,Web瀏覽器附加功能的當前草案中引用了它。 –