javascript - Object.isExtensible() 为真,但 Object.defineProperty() 抛出。为什么?

标签 javascript

在 Firefox 和 Safari 中,我看到 Object.isExtensible() 为 true 的情况,我可以添加一个具有常规属性分配的新属性(即,o.x = y),但是 Object.defineProperty() 抛出“TypeError: Object.defineProperty(...) is not extensible”。

这种情况发生在类型化数组中,也许其他类型也是如此。我正在尝试使用 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。

最佳答案

Note: typed arrays are now in the ES6/ES2015 specification, where ArrayBuffers are actually extensible. This answer is provided for prior reference.


Typed Array specification尽管它使用了 Web IDL,但并未对此明确说明任何内容描述创建的对象,其中说明如下:

Unless otherwise specified, the [[Extensible]] internal property of objects defined in this section has the value true.

我不确定他们为什么将其放入规范中,但他们可能选择使 [[Extensible]] 为真(即使它不可扩展)的一些原因包括:

  • 希望允许来自特定函数/路径的扩展(为 false 时禁止)
  • 保留允许扩展宿主对象的可能性(禁止从 false 更改为 true)

根据the ECMAScript specification (JavaScript 的“标准”版本),宿主对象是否抛出设置变量取决于实现(§8.6.2):

Host objects may implement these internal methods in any manner unless specified otherwise; for example, one possibility is that [[Get]] and [[Put]] for a particular host object indeed fetch and store property values but [[HasProperty]] always generates false. However, if any specified manipulation of a host object's internal properties is not supported by an implementation, that manipulation must throw a TypeError exception when attempted.

规范给出的不变量均不适用于此实例,因此这在技术上是合法的。


注意澄清:即使 [[Extensible]] 为真,宿主对象的内部函数也不一定允许对象被扩展。如果 [[Extensible]] 为 false ( reference ),该规范仅要求不扩展主机对象:

The [[DefineOwnProperty]] internal method of a host object must not permit the addition of a new property to a host object if the [[Extensible]] internal property of that host object has been observed by ECMAScript code to be false.

表 8/9 (§8.6.2) 中的规范中给出的描述本身具有误导性,因为它们仅涉及 native ECMAScript 对象,而不涉及宿主对象——这在表 8 之前的段落中特别指出,宿主对象是不受实现这些表中描述的属性的约束。

关于javascript - Object.isExtensible() 为真,但 Object.defineProperty() 抛出。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19329049/

相关文章:

javascript - 为选中的每个复选框添加和删除隐藏输入

javascript - 如何在 React Js 的 map 函数中使用 Bootstrap Modal 渲染单个元素?

javascript - 使用制表符在文本区域中缩进

Javascript:选择另一个div时显示隐藏的div

javascript - OAuth 同意屏幕 localhost

javascript - Angular 路由不适用于 anchor

javascript - 另一个 map 调用中的异步 Array.map()

javascript - 在javascript中比较数组

javascript - 上传图片 URI 到 Cloudinary

javascript - 如何从异步调用返回响应?