6

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty状态:

可配置:当且仅当此属性描述符的类型可以更改并且可以从相应对象中删除该属性时才为真。默认为false.

所以,我有一个

var x = Object.defineProperty({}, "a", {
    value:true,
    writable:true,
    enumerable:true,
    configurable:false
});

现在我可以玩x.a = falsefor(i in x)等等。但即使描述符应该是不可配置的,我也可以

Object.defineProperty(x, "a", {writable:true}); // others defaulting to false
Object.defineProperty(x, "a", {}); // everything to false
Object.freeze(x); // does the same to the descriptors

反过来,再次将它们设置为 true,或者尝试定义访问器描述符,现在会引发错误。准确地说:Object.defineProperty: invalid modification of non-configurable property.

为什么我可以“降级”描述符,尽管他们说它们是不可配置的?

4

1 回答 1

16

首先,即使configurablefalsewritable也可以从 更改truefalseconfigurable这是is时唯一允许的属性更改false。允许这种转换是因为一些内置属性,包括(最显着)length数组的属性(包括Array.prototype)被指定为writable: true, configurable: false。这是以前 ECMAScript 版本的遗产。如果configurable: false阻止writabletrueto更改,false则无法冻结数组。

Object.defineProperty不像你假设的那样工作。特别是,它处理属性描述符的方式会根据属性是否已经存在而有所不同。如果属性不存在,则描述符应该提供所有属性的定义,因此在使用描述符创建属性之前,描述符中任何缺失的属性都会被分配默认值。但是,对于已经存在的属性,描述符被视为属性当前属性设置的一组增量更改。描述符中未列出的属性不会更改。此外,在增量描述符中与当前属性属性值具有相同值的属性也被认为没有变化。所以以下都是合法的:

Object.defineProperty(x, "a", {writable:false}); // can always change writable to false.
                                                //others attributes, not changed
Object.defineProperty(x, "a", {});     // no attributes, so nothing changes
Object.freeze(x); // same as Object.defineProperty(x, "a", {writable:false});
Object.defineProperty(x, "a", {enumerable:true, configurable: false}); //no change, 
于 2012-03-23T16:49:00.623 回答