原文:
从邮件列表中看到的.
Object.prototype.get = function(){};var o = {};Object.defineProperty(o, "hoge", { value: "OK" });// TypeError: property descriptors must not specify a value or be writable when a getter or setter has been specified
问题描述就是:如果在Object.prototype上添加了名为
get
,set之类的属性的话,再执行
Object.defineProperty()的时候就很有可能发生问题.为什么?
不应该在Object.prototype上添加的属性
下面给出的属性名最不应该添加在Object.prototype上
- get
- set
- value
- writable
为什么?
Object.defineProperty的第三个参数Descriptor是个对象,指定了所定义属性的属性描述符.属性描述符一共有两种.
数据属性描述符(DataDescriptor)和访问器属性描述(AccessorDescriptor).
数据属性描述符对象上不能有get
,set属性,
访问器属性描述符对象上不能有value
,writable属性.
执行defineProperty的时候,在判断属性描述符对象中某个属性是否存在时使用的内部方法是[[HasProperty]].[[HasProperty]]会在[[Prototype]]上寻找属性,也就找到了Object.prototype上定义的那些属性.如果使用[[GetOwnProperty]]来判断的话就不会有这样的问题了.
上例中的问题就是,get和value两个属性不能同时存在,否则会报错.
解决办法
创建一个没有原型的属性描述符对象:
var des = Object.create(null);des.value = 123;Object.defineProperty(obj,"key",des);
也可以使用非标准的魔法属性__proto__:
Object.defineProperty(obj, "key", { __proto__: null, value: 123 });
同样,Object.defineProperties()以及
Object.create()的第二个参数中也有属性描述符对象,也有可能出现同样的问题
.