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

Ber*_*rgi 6 javascript ecmascript-5 defineproperty

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

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

所以,我有一个

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

现在,我可以玩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
Run Code Online (Sandbox Code Playgroud)

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

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

All*_*ock 16

首先,即使configurablefalse,writable可以从改变truefalse.这是允许的时候才会属性更改configurablefalse.允许此转换是因为某些内置属性(包括(最值得注意的))指定length了数组(包括Array.prototype)的属性writable: true, configurable: false.这是以前ECMAScript版本的遗产.如果configurable: false防止改变writabletruefalse那么这将是不可能冻结阵列.

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, 
Run Code Online (Sandbox Code Playgroud)