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?
First, even when
configurable
isfalse
,writable
can be changed fromtrue
tofalse
. This is the only attribute change allowed whenconfigurable
isfalse
. This transition was allowed because some built-in properties including (most notably) thelength
property of arrays (includingArray.prototype
) are specified to bewritable: true, configurable: false
. This is a legacy of previous ECMAScript editions. Ifconfigurable: false
prevented changingwritable
fromtrue
tofalse
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: