Fiddle
var Assertion = function() { return { "dummy": "data" }; } Object.defineProperty(Object.prototype, 'should', { set: function(){}, get: function(){ return new Assertion(this); } }); // Insert magic here. // This needs to be false console.log(({}).should === undefined);
What options do I have in ES5 to undo a defineProperty
call ?
No silly suggestions like Object.defineProperty = function() { }
please.
The following Object.defineProperty(Object.prototype, 'should', {})
does not work
and Object.defineProperty(Object.prototype, 'should', { value: undefined })
Throws a Uncaught TypeError: Cannot redefine property: defineProperty
in V8
Object.defineProperty(Object.prototype, 'should', { set: function() {}, get: function() { return undefined; } });
Throws the same error
delete Object.prototype.should
also does not work
defineProperty() The static method Object. defineProperty() defines a new property directly on an object, or modifies an existing property on an object, and returns the object.
Using getter syntax you create a property which, prior to ES2015, you had to know the name of at the time that you were writing the code. Object. defineProperty allows you to perform the same as the above but, even before ES2015, does not require you to know the name of the property in advanced.
Object. defineProperty allows you to set whether or not the property is enumerable, writable, and configurable as well as a value or a get/set (getter/setter) pair (see MDN Object.
A property descriptor is a record with some of the following attributes: value. The value associated with the property (data descriptors only). writable. true if and only if the value associated with the property may be changed (data descriptors only).
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.
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