使用Object.defineProperty重新定义属性时需要注意的一点

来源:互联网 发布:java环境变量一键配置 编辑:程序博客网 时间:2024/05/16 00:57

使用Object.defineProperty重新定义属性时需要注意的一点,具体说来:

当一个对象已存在某属性,重新定义该属性(如果允许)时,若未指定属性描述器的enumerable或configurable,则其默认值为原有属性描述器的对应的enumerable或configurable值。

TL;DR?

再次定义一个对象的属性时,新属性描述器中未指定的enumerable或configurable其默认值将由原属性描述器提供,而不再是false。

看来长话短说不了,依旧这么长,那就不废话了,举例说明:

设有一对象foo

var foo={    firstName: "Foo",    lastName: "Bar",    get fullName(){        return this.firstName+" "+this.lastName;    }};//#test1console.log(foo.fullName);//"Foo Bar"

现需对foo进行升级

实现:
1. 支持middleName;
2. 在JSON.stringify(foo)时属性fullName不被序列化;

Object.defineProperty(foo,"fullName",{    configurable:true,    get: function(){        var fullName=this.firstName;        if(this.middleName)            fullName+=" "+this.middleName;        fullName+=" "+this.lastName;        return fullName;    }});//#test2foo.middleName="Tim";console.log(foo.fullName);//"Foo Tim Bar"//#test3console.log(JSON.stringify(foo));//{"firstName":"Foo","lastName":"Bar","fullName":"Foo Tim Bar","middleName":"Tim"}

升级后存在bug

从#test3的输出结果可以看出:JSON.stringify(foo)时属性fullName仍被序列化了。

于是检查fullName的属性描述器

console.log(Object.getOwnPropertyDescriptor(foo,"fullName"));//{get: function fullName(){...}, set:undefined, enumerable:true, configurable:true}

发现enumerable值仍然是true,未指定应该是false才对呀。

是不是浏览器有bug?

换了个浏览器,亦存在同样问题。

浏览器没有错,机制如此而已

只好显式指定enumerable,打补丁修复现有问题。

(function(){    var descriptor=Object.getOwnPropertyDescriptor(foo,"fullName");    descriptor.enumerable=false;    Object.defineProperty(foo,"fullName",descriptor);})();//#test4console.log(JSON.stringify(foo));//{"firstName":"Foo","lastName":"Bar","middleName":"Ent"}

总算搞定了,坑爹呀!

所以说,使用Object.defineProperty重新定义属性时需要注意

0 0