javascript 如何撤消 Object.defineProperty 调用?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7141210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 23:04:57  来源:igfitidea点击:

How do I undo a Object.defineProperty call?

javascriptgoogle-chromenode.jsdefineproperty

提问by Raynos

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 definePropertycall ?

在 ES5 中有哪些选项可以撤消defineProperty呼叫?

No silly suggestions like Object.defineProperty = function() { }please.

请不要愚蠢的建议Object.defineProperty = function() { }

The following Object.defineProperty(Object.prototype, 'should', {})

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

does not work

确实不工作

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

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

Throws a Uncaught TypeError: Cannot redefine property: definePropertyin V8

Uncaught TypeError: Cannot redefine property: defineProperty在 V8 中抛出一个

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

Throws the same error

抛出同样的错误

delete Object.prototype.shouldalso does not work

delete Object.prototype.should不起作用

回答by user123444555621

In general, you can't undo a definePropertycall, since there's no undo stack or something. The JS engine does not keep track of previous attribute descriptors.

通常,您无法撤消defineProperty调用,因为没有撤消堆栈或其他东西。JS 引擎不会跟踪以前的属性描述符。

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 removeor reconfigurean attribute, or overwriteits value. As mentioned in the other answer, the configurableflag is required to be trueif you want to remove or reconfigure. Once a property is defined with configurable:false, you cannot change the configurableflag.

您可以做的是删除重新配置属性,或覆盖其值。如另一个答案中所述,如果您想删除或重新配置,configurable则需要该标志true。一旦使用 定义了属性configurable:false,就无法更改configurable标志。



To remove an attribute (this is supposedly what you want to do), use delete:

要删除属性(这应该是您想要做的),请使用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 definePropertyagain and pass a different descriptor:

要重新配置,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

As shown in this sample, you can use definePropertyto switch between accessor (get/set) and data (value) properties.

如本示例所示,您可以使用defineProperty在访问器 ( get/ set) 和数据 ( value) 属性之间切换。



To overwrite, use simple assignment. In this case, you need the writableflag to be true. Obviously this does not work with accessor properties. It even throws an exception:

要覆盖,请使用简单分配。在这种情况下,您需要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!
});

Note that writabledefaults to falsewhen you use defineProperty, but truewhen you use the simple syntax o.attr = val;to define a (previously not existing) property.

请注意,当您使用时writable默认为,但当您使用简单语法定义(以前不存在的)属性时。falsedefinePropertytrueo.attr = val;