Ответ 1
В общем случае вы не можете отменить вызов 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
для переключения между свойствами accessor (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;
для определения свойства (ранее не существующего).