In general, you can't undo a defineProperty
call, since there's no undo stack or something. The JS engine does not keep track of previous attribute descriptors.
For example,
Object.defineProperty(Object.prototype, 'foo', {
configurable: true,
value: 1,
enumerable: false
});
Object.defineProperty(Object.prototype, 'foo', {
get: function () {
alert('You cannot revert me');
return 2;
},
enumerable: true
});
What you can do is remove or reconfigure an attribute, or overwrite its value. As mentioned in the other answer, the configurable
flag is required to be true
if you want to remove or reconfigure.
Once a property is defined with configurable:false
, you cannot change the configurable
flag.
To remove an attribute (this is supposedly what you want to do), use delete
:
Object.defineProperty(Object.prototype, 'foo', {
configurable: true, // defaults to false
writable: false,
value: 1
});
delete Object.prototype.foo;
console.log(Object.prototype.hasOwnProperty('foo')); // false
To reconfigure, use defineProperty
again and pass a different descriptor:
Object.defineProperty(Object.prototype, 'foo', {
configurable: true,
get: ...
set: ...
});
Object.defineProperty(Object.prototype, 'foo', {
value: undefined
});
console.log({}.foo); // undefined
console.log(Object.prototype.hasOwnProperty('foo')); // true
As shown in this sample, you can use defineProperty
to switch between accessor (get
/set
) and data (value
) properties.
To overwrite, use simple assignment. In this case, you need the writable
flag to be true
. Obviously this does not work with accessor properties. It even throws an exception:
Object.defineProperty(Object.prototype, 'foo', {
configurable: true,
value: 1,
writable: true // defaults to false
});
Object.prototype.foo = undefined;
console.log(Object.prototype.foo); // undefined
console.log(Object.prototype.hasOwnProperty('foo')); // true
Object.defineProperty(Object.prototype, 'foo', {
get: function () {
return 1;
},
writable: true // JS error!
});
Note that writable
defaults to false
when you use defineProperty
, but true
when you use the simple syntax o.attr = val;
to define a (previously not existing) property.
accessor
by assigning a new value to the property like thisobj.foo = 'new value';
? in other word why we have to either delete the property first or reconfigure it to get rid of that accessor – Mathamathe