javascript – 为什么我可以设置不可配置属性描述符的[可枚举性和可写性]?

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

configurable:
True if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object. Defaults to false.

所以,我有一个

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

现在我可以使用x.a = false,for(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:对不可配置属性的无效修改.

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

最佳答案
首先,即使可配置为假,可写也可以从true更改为false.这是可配置为false时允许的唯一属性更改.允许此转换是因为某些内置属性(包括(最值得注意的))数组的长度属性(包括Array.prototype)被指定为可写:true,configurable:false.这是以前ECMAScript版本的遗产.如果可配置:false阻止将writable从true更改为false,那么就不可能冻结数组.

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

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, 

转载注明原文:javascript – 为什么我可以设置不可配置属性描述符的[可枚举性和可写性]? - 代码日志