2011-06-08 31 views
2

我在瀏覽關於添加到對象的新功能的MDC。其中之一Object.preventExtensions據說可以防止對象原型的突變,這可以通過使用Object.getPrototypeOf__proto__來獲得。Object.preventExtensions實際上允許__proto__的變異?

但是,在Chrome上,它似乎只是允許對象原型的變體。這可以通過只執行對relevant page代碼確認:

// EXTENSION (only works in engines supporting __proto__ 
// (which is deprecated. Use Object.getPrototypeOf instead)): 
// A non-extensible object's prototype is immutable. 

var fixed = Object.preventExtensions({}); 
fixed.__proto__ = { oh: "hai" }; // throws a TypeError 

我沒有得到這個TypeError,並fixed.__proto__.oh === 'hai',所以儘管它應該被禁止已設置。我也可以在編碼時加上它,如Object.getPrototypeOf(fixed).oh = 'hai'

這是否意味着Chrome對此功能有不同的解釋?如何防止擴展到對象的原型(在Chrome中)?

回答

4

不,Chrome和Mozilla都實現了相同規範的標準部分。仔細閱讀:

Object.preventExtensions只防止 添加自己的屬性。屬性 仍可以添加到對象 原型。

.__proto__有關的所有內容都是非標準的,Chrome可以採用不同的實施方式。您只展示了Chrome實現的細節與.__proto__的不同,在我看來,更直觀:規範說明原型仍然可以擴展,因此您應該仍然可以對其進行變更。那麼問題就變成爲什麼Mozilla實施它的方式?

例如,下面的代碼的工作原理相同的Chrome和FF:

var fixed = Object.preventExtensions({}); 
Object.getPrototypeOf(fixed).p = 99; 
fixed.p; // 99 

顯然原型仍然是可變的。 Chrome的實現.__proto__是有意義的。

因此,爲了防止原型的擴展,這樣做的分別:

var fixed = Object.preventExtensions({}); 
Object.preventExtensions(Object.getPrototypeOf(fixed)); 
Object.getPrototypeOf(fixed).p = 99; // TypeError: Can't add property p, object is not extensible 
2

在ECMAScript中5,對象有一個布爾internal property命名[[Extensible]],這個屬性被設置爲false當你調用Object.preventExtensions方法,並經過也就是說,沒有新的自己的屬性可以添加到對象。

在Chrome 14.0.786.0上,分配給__proto__會按照您的預期拋出TypeError

但請記住,__proto__擴展非標準,所以它的行爲可能會有所不同,當然,語法上它是一種「財產分配」,但是在內部它不會「添加自己的財產」,它變異了對象的原型,這是任何標準方法都無法做到的事情。

關於Object.getPrototypeOf方法,你告訴我們,它只是檢索對象的原型,在你fixed對象的情況爲例,它的Object.prototype對象:

Object.getPrototypeOf(fixed) === Object.prototype; // true 

所以,你的例子:

Object.getPrototypeOf(fixed).oh = 'hai' 

相當於:

Object.prototype.oh === 'hai';