В общем, вы не можете отменить вызов defineProperty
, так как нет стека отмены или чего-то еще.Механизм JS не отслеживает предыдущие дескрипторы атрибутов.
Например,
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
});
Что вы можете сделать, это удалить или переконфигурировать атрибут или перезаписать его значение.Как упоминалось в другом ответе, флаг configurable
должен быть true
, если вы хотите удалить или перенастроить.Как только свойство определено с помощью configurable:false
, вы не можете изменить флаг configurable
.
Чтобы удалить атрибут (это, предположительно, то, что вы хотите сделать), используйте 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
Чтобы переконфигурировать, снова используйте defineProperty
и передайте другой дескриптор:
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
Как показано в этом примере, вы можете использовать defineProperty
для переключения между аксессором (get
/ set
) и свойства данных (value
).
Для перезаписи используйте простое назначение.В этом случае вам нужно, чтобы флаг writable
был true
.Очевидно, что это не работает со свойствами доступа.Он даже генерирует исключение:
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!
});
Обратите внимание, что writable
по умолчанию false
, когда вы используете defineProperty
, но true
, когда вы используете простой синтаксис o.attr = val;
для определения (ранеене существует) собственность.