如何撤消Object.defineProperty调用? [英] How do I undo a Object.defineProperty call?

查看:923
本文介绍了如何撤消Object.defineProperty调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

小提琴

  var Assertion = function(){
return {dummy:data};


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

//在这里插入魔法。

//这需要为false
console.log(({})。=== undefined);

ES5中有什么选项可以撤消 defineProperty call?



没有愚蠢的建议,像 Object.defineProperty = function(){} p>

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



不会不工作



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



href =http://jsfiddle.net/gmnHp/15/> Uncaught TypeError:无法在V8中重新定义属性:defineProperty

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

抛出同样的错误



delete Object.prototype.should 不工作

解决方案

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



例如,

  Object.defineProperty(Object.prototype,'foo',{
可配置:true,
值:1,
enumerable:false
});
Object.defineProperty(Object.prototype,'foo',{
get:function(){
alert('You can not revert me');
return 2;
},
enumerable:true
});

您可以做的是删除重新配置属性,或者覆盖其值。正如在另一个答案中提到的那样,如果要删除或重新配置,可配置标志必须为 true
一旦使用可配置:false 定义了一个属性,您将无法更改可配置标志。






要删除一个属性(这应该是你想要做的),使用 delete
$ p $ Object.defineProperty(Object.prototype,'foo',{
可配置:true,/ /默认为false
可写:false,
值:1
});
delete Object.prototype.foo;
console.log(Object.prototype.hasOwnProperty('foo')); // false






要重新配置,请使用 defineProperty 再传递一个不同的描述符:

  Object.defineProperty(Object.prototype, 'foo',{
可配置:true,
获得:...
集合:...
});
Object.defineProperty(Object.prototype,'foo',{
value:undefined
});
console.log({}。foo); //未定义
console.log(Object.prototype.hasOwnProperty('foo')); // true

如此示例所示,您可以使用 defineProperty 在accessor( get / set )和data( value)之间切换)属性。






要覆盖,请使用简单赋值。在这种情况下,您需要可写标志为 true 。显然这不适用于访问器属性。它甚至会抛出一个异常:

  Object.defineProperty(Object.prototype,'foo',{
configurable:true ,
值:1,
可写:true //默认为false
});
Object.prototype.foo = undefined;
console.log(Object.prototype.foo); //未定义
console.log(Object.prototype.hasOwnProperty('foo')); // true

Object.defineProperty(Object.prototype,'foo',{
get:function(){
return 1;
},
可写:true // JS错误!
});

请注意,可写默认为<$ c当您使用简单语法时,使用 defineProperty ,但 true 时,$ c> false o.attr = val; 来定义一个(以前不存在的)属性。


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 defineProperty call ?

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

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

does not work

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

Throws a Uncaught TypeError: Cannot redefine property: defineProperty in V8

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

Throws the same error

delete Object.prototype.should also does not work

解决方案

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

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 remove or reconfigure an attribute, or overwrite its value. As mentioned in the other answer, the configurable flag is required to be true if you want to remove or reconfigure. Once a property is defined with configurable:false, you cannot change the configurable flag.


To remove an attribute (this is supposedly what you want to do), use 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 defineProperty again and pass a different descriptor:

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 defineProperty to switch between accessor (get/set) and data (value) properties.


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

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 writable defaults to false when you use defineProperty, but true when you use the simple syntax o.attr = val; to define a (previously not existing) property.

这篇关于如何撤消Object.defineProperty调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆