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
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,
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With