Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
117 views
in Technique[技术] by (71.8m points)

javascript - Why can I set [enumerability and] writability of unconfigurable property descriptors?

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

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.

So, I have a

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

Now I can play with x.a = false, for(i in x) etc. But even though the descriptor is should be unconfigurable, I can do

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

The other way round, setting them to true again, or trying to define an accessor descriptor, raises errors now. To be exact: Object.defineProperty: invalid modification of non-configurable property.

Why can I "downgrade" descriptors though they say they were non-configurable?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First, even when configurable is false, writable can be changed from true to false. This is the only attribute change allowed when configurable is false. This transition was allowed because some built-in properties including (most notably) the length property of arrays (including Array.prototype) are specified to be writable: true, configurable: false. This is a legacy of previous ECMAScript editions. If configurable: false prevented changing writable from true to false then it would be impossible to freeze arrays.

Object.defineProperty doesn't work quite like you're assuming. In particular, how it processes the property descriptor works differently depending upon whether or not the property already exists. If a property does not exist, the descriptor is supposed to provide a definition of all attributes so any missing attributes in the descriptor are assigned default values before the descriptor is used to create the property. However, for an already existing property the descriptor is taken as a set of delta changes from the current attribute settings of the property. Attributes that are not listed in the descriptor are not changed. Also, a attribute that has the same value in the delta descriptor as the current property attribute value is also consider no change. So the following are all legal:

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, 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...