53 Stimmen

Wie kann ich einen Object.defineProperty-Aufruf rückgängig machen?

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);

Welche Optionen habe ich in ES5, um eine Rückgängigmachung defineProperty anrufen?

Keine dummen Vorschläge wie Object.defineProperty = function() { } bitte.

Die folgenden Object.defineProperty(Object.prototype, 'should', {})

fait nicht funktionieren

et Object.defineProperty(Object.prototype, 'should', { value: undefined })

Wirft eine Uncaught TypeError: Cannot redefine property: defineProperty in V8

Object.defineProperty(Object.prototype, 'should', { 
    set: function() {},
    get: function() { return undefined; }
});

Wirft die gleicher Fehler

delete Object.prototype.should auch funktioniert nicht

55voto

user123444555621 Punkte 139356

In der Regel können Sie eine Operation nicht rückgängig machen. defineProperty Aufruf, da es keinen Rückgängig-Stapel oder ähnliches gibt. Die JS-Engine behält keine vorherigen Attributdeskriptoren im Auge.

Zum Beispiel,

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
});

Was Sie tun können, ist entfernen ou neu konfigurieren ein Attribut, oder überschreiben. seinen Wert. Wie in der anderen Antwort erwähnt, ist die configurable Flagge muss sein true wenn Sie sie entfernen oder umkonfigurieren möchten. Sobald eine Eigenschaft definiert ist mit configurable:false können Sie die configurable Flagge.


Um ein Attribut zu entfernen (was Sie vermutlich tun wollen), verwenden Sie 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

Zum Umkonfigurieren verwenden Sie defineProperty erneut und übergibt einen anderen Deskriptor:

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

Wie in diesem Beispiel gezeigt, können Sie Folgendes verwenden defineProperty um zwischen Accessor ( get / set ) und Daten ( value ) Eigenschaften.


Zum Überschreiben verwenden Sie die einfache Zuweisung. In diesem Fall benötigen Sie die writable Flagge zu sein true . Offensichtlich funktioniert dies nicht mit Accessor-Eigenschaften. Es löst sogar eine Ausnahme aus:

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!
});

Beachten Sie, dass writable wird standardmäßig auf false wenn Sie defineProperty が、しかし true wenn Sie die einfache Syntax verwenden o.attr = val; um eine (bisher nicht vorhandene) Eigenschaft zu definieren.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X