Object.preventExtensions实际上允许__proto__的变异?

pim*_*vdb 4 javascript object ecmascript-5 prototype-programming

我正在浏览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
Run Code Online (Sandbox Code Playgroud)

我没有得到这个TypeError,fixed.__proto__.oh === 'hai'所以它已被设置,即使它应该被禁止.我也可以在编码时添加它Object.getPrototypeOf(fixed).oh = 'hai'.

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

dav*_*vin 5

不,Chrome和Mozilla都实现了规范的标准部分相同.仔细读:

Object.preventExtensions仅阻止添加自己的属性.属性仍然可以添加到对象原型中.

一切都是.__proto__非标准的,Chrome可以以不同的方式实现.您只展示了Chrome以.__proto__不同的方式实现细节,在我看来,更直观地说:规范说原型仍然是可扩展的,所以你应该仍然能够改变它是有意义的.那么问题就变成了为什么Mozilla以这种方式实现它?

例如,以下代码在Chrome和FF上的工作方式相同:

var fixed = Object.preventExtensions({});
Object.getPrototypeOf(fixed).p = 99;
fixed.p; // 99
Run Code Online (Sandbox Code Playgroud)

很明显,原型仍然是可变的.这对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
Run Code Online (Sandbox Code Playgroud)