Object.isExtensible() 为 true,但 Object.defineProperty() 会抛出.为
Object.isExtensible() is true, but Object.defineProperty() throws. Why?
在Firefox和Safari中,我看到了Object.isExtensible()
为真的情况,我可以添加一个具有常规属性赋值的新属性(即o.x = y
(,但是Object.defineProperty()
抛出"TypeError: Object.defineProperty(...不可扩展"。
这种情况发生在类型化数组中,也许其他类型的数组也是如此。我尝试使用isExtensible()
来确保我不尝试在对象上定义属性。
我可以尝试/捕获定义属性,但我想了解这里发生了什么。有什么想法吗?
下面是一个关于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
实际上是可扩展的。此答案仅供事先参考。
类型数组规范没有明确说明这一点,尽管它使用 Web IDL 来描述创建的对象,其中说:
除非另有指定,否则本节中定义的对象的 [[可扩展]] 内部属性的值为 true。
我不确定他们为什么把它放在规范中,但他们可能选择使[[Extensible]]
成为现实的一些原因,即使它不可扩展,包括:
- 想要允许来自特定函数/路径的扩展(当它为 false 时禁止(
- 保留允许扩展主机对象的可能性(禁止从 false 更改为 true(
根据 ECMAScript 规范(JavaScript 的"标准"版本(,主机对象在设置变量时是否抛出取决于实现 (§8.6.2(:
除非另有说明,否则主机对象可以以任何方式实现这些内部方法;例如,一种可能性是特定主机对象的
[[Get]]
和[[Put]]
确实获取和存储属性值,但[[HasProperty]]
总是生成 false。但是,如果实现不支持对主机对象内部属性的任何指定操作,则该操作在尝试时必须引发TypeError
异常。
规范给出的所有不变量都不适用于这种情况,因此这在技术上是合法的。
需要澄清的注意事项:即使[[Extensible]]
为 true,主机对象的内部函数也不必允许扩展对象。 该规范仅要求在 [[Extensible]]
为 false 时不扩展主机对象(参考(:
如果 ECMAScript 代码观察到主机对象的
[[Extensible]]
内部属性为 false,则主机对象的[[DefineOwnProperty]]
内部方法不得允许向主机对象添加新属性。
Table 8/9 (§8.6.2( 中规范中给出的描述本身具有误导性,因为它们只涉及本机 ECMAScript 对象,而不涉及主机对象 - 这在表 8 前面的段落中特别指出,主机对象不受这些表中描述的属性的实现的约束。
这种行为依赖于严格模式和JavaScript引擎。
在 V8 (Chrome( 中,如果严格模式处于关闭状态,o.x = y
将成功,但不会向 o.x
分配任何内容,而Object.defineProperty
将始终抛出异常,而不管严格模式如何。
在严格模式下o.x
将引发异常。
在 Rhino 中,Object.defineProperty
会抛出异常,o.x = 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)
- 函数未在Object.keys或Object.getOwnPropertyNames下列出,但可以调用
- delete在Object上效率低下,但在DOM Element's的数据属性,与null out相比
- 有没有一种方法可以列出Ember.Object的所有绑定
- 如何取消object.prototypes javascript的一个函数
- 为什么是文档.旧版应用程序中的DOM-object.properties为null
- 将*.js文件的内容放入Object中
- Object.prototype using 'this'
- 使用Object.create()的角度服务继承
- 如何使用object.assign()从其他对象引用基本对象属性
- 循环的数组推入在Object容器中具有不同的值
- reducers在redux中得到Function not Object,what'it’他错了
- JSON.stringify和Object.keys在同一个对象上产生不同的结果
- 在使用object.create创建的对象中使用super
- Join架构验证:Join.object定义数组中的有效键
- jquery打印[object XMLDocument]而不是文件内容
- ExtJS 4 Object.prototype fail
- JavaScript-从对象数组中输出随机OBJECT
- 为什么“{}+1”在Chrome和Firefox中排名第一,而字符串'[object object]1'
- 什么是“;原型;通过JavaScript中的Object Literal Notation创建的对象的链接
- 如何在Node.js控制台中发现Object API