如何撤消Object.defineProperty调用?

时间:2011-08-21 21:11:54

标签: javascript google-chrome node.js defineproperty

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

我在ES5中有哪些选项来撤消defineProperty来电?

不要像Object.defineProperty = function() { }那样愚蠢的建议。

以下Object.defineProperty(Object.prototype, 'should', {})

not work

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

在V8中投掷Uncaught TypeError: Cannot redefine property: defineProperty

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

引发same error

delete Object.prototype.shoulddoes not work

1 个答案:

答案 0 :(得分:39)

通常,您无法撤消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来定义({1}}时,o.attr = val;默认为{{1}} )财产。