4

我正在浏览 MDC 关于添加到 Object 的新功能。其中之一,Object.preventExtensions,据说可以防止对象原型的突变,可以通过使用Object.getPrototypeOf或获得__proto__

然而,在 Chrome 上,它似乎只是允许对对象的原型进行更改。这可以通过执行相关页面上的代码来确认:

// 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, and fixed.__proto__.oh === 'hai', 所以它已经被设置了,即使它应该被禁止。我也可以在编码时添加它Object.getPrototypeOf(fixed).oh = 'hai'

这是否意味着 Chrome 对这个功能有不同的解释?如何防止扩展对象原型(在 Chrome 中)?

4

2 回答 2

5

不,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
于 2011-06-08T15:43:30.503 回答
2

在 ECMAScript 5 中,对象有一个名为的布尔内部属性,当你调用方法时[[Extensible]]这个属性被设置为,之后就不能再给对象添加新的自己的属性了。falseObject.preventExtensions

在 Chrome 14.0.786.0 上,分配给__proto__throws aTypeError如你所料。

但是请记住,__proto__扩展是非标准的,所以它的行为可能会有所不同,当然在语法上它是一个“属性分配”,但在内部它不会“添加自己的属性”,它会改变对象的原型,这不是可以通过任何标准方法进行。

关于Object.getPrototypeOf您向我们展示的方法示例,它只是检索对象的原型,就您的fixed对象而言,它是Object.prototype对象:

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

所以你的例子:

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

相当于:

Object.prototype.oh === 'hai';
于 2011-06-08T15:48:36.657 回答