https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty州:
配置: 当且仅当可以更改此属性描述符的类型并且可以从相应对象中删除属性时才返回true。默认为
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: invalid modification of non-configurable property
。
为什么我可以“降级”描述符虽然他们说它们是不可配置的?
答案 0 :(得分:16)
首先,即使configurable
为false
,writable
也可以从true
更改为false
。这是configurable
为false
时允许的唯一属性更改。允许此转换是因为某些内置属性(包括(最值得注意的))数组的length
属性(包括Array.prototype
)被指定为writable: true, configurable: false
。这是以前ECMAScript版本的遗产。如果configurable: 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,