原文:http://d.hatena.ne.jp/teramako/20121129/p1
從ES-Discuss郵件列表中看到的.
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()的第二個參數中也有屬性描述符對象,也有可能出現同樣的問題
.