[英]Object.isExtensible() is true, but Object.defineProperty() throws. Why?
在Firefox和Safari中我看到Object.isExtensible()
為true的情況,我可以添加一個帶有常規屬性賦值的新屬性(即ox = y
),但是Object.defineProperty()
會拋出“TypeError:Object.defineProperty” (...)不可擴展“。
這種情況發生在類型數組中,也可能是其他類型。 我正在嘗試使用isExtensible()
來確保我不嘗試在對象上定義屬性。
我可以將defineProperty放在try / catch中,但我想了解這里發生了什么。 有任何想法嗎?
這是jsfiddle的一個例子: http : //jsfiddle.net/justinfagnani/qvgnk/
和代碼:
function addProperty(o, name, value) {
if (Object.isExtensible(o)) {
Object.defineProperty(o, name, {'value': value});
return true;
}
return false;
}
console.log(addProperty(new Date(), 'foo', 1));
console.log(addProperty(new ArrayBuffer(), 'foo', 1));
這應該至少為每次調用打印true或false。 在Firefox中,它會拋出ArrayBuffer。
注意:類型化數組現在在ES6 / ES2015規范中,其中
ArrayBuffer
實際上是可擴展的。 此答案僅供先前參考。
Typed Array規范沒有明確說明這一點,盡管它使用Web IDL來描述創建的對象,其中說明如下:
除非另有說明,否則本節中定義的對象的[[Extensible]]內部屬性值為true 。
我不確定為什么他們把這個放在規范中,但是為什么他們可能選擇使[[Extensible]]
真,即使它不可擴展,也有一些原因包括:
根據ECMAScript規范 (JavaScript的“標准”版本),主機對象是否拋出設置變量是依賴於實現的(第8.6.2節 ):
除非另有說明,否則Host對象可以以任何方式實現這些內部方法 ; 例如,一種可能性是特定主機對象的
[[Get]]
和[[Put]]
確實獲取並存儲屬性值,但[[HasProperty]]
始終生成false。 但是,如果實現不支持對宿主對象的內部屬性的任何指定操作,則該操作必須在嘗試時拋出TypeError
異常。
規范給出的不變量都不適用於此實例,因此這在技術上是合法的。
需要注意的是:即使[[Extensible]]
為真,主機對象的內部函數也不必允許對象進行擴展。 規范僅強制要求在[[Extensible]]
為false( 引用 )時不擴展宿主對象:
如果ECMAScript代碼觀察到該主機對象的
[[Extensible]]
內部屬性為false,則主機對象的[[DefineOwnProperty]]
內部方法不允許向主機對象添加新屬性。
表8/9(第8.6.2節 )中的規范中給出的描述本身就是誤導性的,因為它們只涉及本機ECMAScript對象,而不是主機對象 - 這在表8之前的段落中具體說明,主機對象不是主題實現這些表中描述的屬性。
我相信這種行為取決於嚴格模式和JavaScript引擎。
在V8(Chrome)中,如果禁用嚴格模式,則ox = y
將成功,但不會向ox
分配任何內容,而Object.defineProperty
將始終拋出異常,無論嚴格模式如何。
在嚴格模式下, ox
會拋出異常。
在Rhino中, Object.defineProperty
將拋出異常, ox = y
將無聲地失敗。
這里有些例子:
/usr/local/Cellar/tomcat6/6.0.37 >rhino -strict
Rhino 1.7 release 4 2012 06 18
js> var o = {a: 132};
js> Object.freeze(o);
[object Object]
js> Object.isExtensible(o);
false
js> o.x = 789;
789
js> o.x;
js> Object.defineProperty(o,'name',{value: 789})
js: uncaught JavaScript runtime exception: TypeError: Cannot add properties to this object because extensible is false.
在V8中
/usr/local/Cellar/tomcat6/6.0.37 >node
> var o = {a: 123}
undefined
> Object.freeze(o)
{ a: 123 }
> Object.isExtensible(o)
false
> o.x = 13
13
> o.x
undefined
> Object.defineProperty(o,'name',{value:123})
TypeError: Cannot define property:name, object is not extensible.
at Function.defineProperty (native)
at repl:1:9
at REPLServer.self.eval (repl.js:110:21)
at Interface.<anonymous> (repl.js:239:12)
at Interface.EventEmitter.emit (events.js:95:17)
at Interface._onLine (readline.js:202:10)
at Interface._line (readline.js:531:8)
at Interface._ttyWrite (readline.js:760:14)
at ReadStream.onkeypress (readline.js:99:10)
at ReadStream.EventEmitter.emit (events.js:98:17)
在嚴格的模式
/usr/local/Cellar/tomcat6/6.0.37 >node --use_strict
> var o = {a: 123};
undefined
> Object.freeze(o);
{ a: 123 }
> Object.isExtensible(o);
false
> o.x = 13
TypeError: Can't add property x, object is not extensible
at repl:1:6
at REPLServer.self.eval (repl.js:110:21)
at Interface.<anonymous> (repl.js:239:12)
at Interface.EventEmitter.emit (events.js:95:17)
at Interface._onLine (readline.js:202:10)
at Interface._line (readline.js:531:8)
at Interface._ttyWrite (readline.js:760:14)
at ReadStream.onkeypress (readline.js:99:10)
at ReadStream.EventEmitter.emit (events.js:98:17)
at emitKey (readline.js:1095:12)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.