天天看點

[Effective JavaScript 筆記]第47條:絕不要在Object.prototype中增加可枚舉的屬性

[Effective JavaScript 筆記]第47條:絕不要在Object.prototype中增加可枚舉的屬性

之前的幾條都不斷地重複着for...in循環,它便利好用,但又容易被原型污染。for...in循環最常見的用法是枚舉字典中的元素。這裡就是從側面提出不要在共享的Object.prototype中增加可枚舉的屬性。這就導緻,我們在開發的時候,不能在Object.prototype中添加有用的方法。如,我們想增加一個産生對象屬性名數組的allKeys方法将會怎麼樣?Object.prototype.a

之前的幾條都不斷地重複着for...in循環,它便利好用,但又容易被原型污染。for...in循環最常見的用法是枚舉字典中的元素。這裡就是從側面提出不要在共享的Object.prototype中增加可枚舉的屬性。

這就導緻,我們在開發的時候,不能在Object.prototype中添加有用的方法。如,我們想增加一個産生對象屬性名數組的allKeys方法将會怎麼樣?

Object.prototype.allKeys=function(){
    var res=[];
    for(var key in this){
       res.push(key);
    }
    return res;
}
           

上面的方法污染了它自身。

({a:1,b:2,c:3}).allKeys();//['allKeys','a','b','c']           

可以用之前說的方法改進allKeys方法忽略掉Object.prototype中的屬性。

獨立為函數

把要添加的方法獨立為一個函數。

function allKeys(obj){
    var res=[];
    for(var key in this){
       res.push(key);
    }
    return res;
}
           

這樣就可以使用,而又可以不污染到原型。for...in循環也不會出錯。

設定為不可枚舉

如果想在Object.prototype中增加屬性,ES5提供了Object.defineProperty方法,可以定義一個對象的屬性并指定該屬性的中繼資料。通過設定其可枚舉性為false使其在for...in循環中不可見。

Object.defineProperty(Object.prototype,'allKeys',{
    value:function(){
        var res=[];
        for(var key in this){
           res.push(key);
        }
        return res;
    },
    writable:true,
    enumerable:false,
    configurable:true
});
           

調用一下可得

({a:1,b:2,c:3}).allKeys();//['a','b','c']           

上面的代碼不會污染其他所有Object執行個體的所有for...in循環。事實上,當你需要增加一個不應該在for...in循環中出現的屬性時,Object.defineProperty方法可以用來定義屬性。

提示

  • 避免在Object.prototype中增加屬性
  • 考慮編寫一個函數代替Object.prototype方法
  • 如果你确定需要在Object.prototype中增加屬性,使用ES5中的Object.defineProperty方法将它們定義為不可枚舉的屬性

版權聲明

翻譯的文章,版權歸原作者所有,隻用于交流與學習的目的。

原創文章,版權歸作者所有,非商業轉載請注明出處,并保留原文的完整連結。

繼續閱讀