細說 Javascript 對象篇(四) : for in 循環

如同 in 運算符同樣,使用 for in 循環遍歷對象屬性時,也將往上遍歷整個原型鏈。javascript

// Poisoning Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
for(var i in foo) {
    console.log(i); // prints both bar and moo
}

這裏咱們要注意兩點,一是 for in 循環會忽略 enumerable 設置爲 false 的屬性。例如一個數組的 length 屬性。第二是,因爲 for in 會遍歷整個原型鏈,因此當原型鏈過長時,會對性能形成影響。java

enumerable 是個很陌生的詞彙,實際上,你很難在 javascript 中發現它的影子,而它實際上也是做者從 ruby 中借鑑而來的。建立 enumerable 的目的不是爲了獨立使用,而是採用「混用」的方式,而 Prototype 中不少方法都混用了 enumerable,因此它能夠說是 prototype 的奠定石。這裏不作詳細介紹,詳細內容能夠參考 - Enumerablegit

因爲咱們無法改變 for in 循環自己的行爲,因此咱們只能採起其餘方法來過濾掉那些不但願出如今循環內的屬性,經過 《細說 Javascript 對象篇(三) : hasOwnProperty》 咱們知道 hasOwnProperty 方法是能夠作到這一點的。github

使用 hasOwnProperty 過濾

仍然使用上個例子:segmentfault

// Poisoning Object.prototype
Object.prototype.bar = 1;

var foo = {moo: 2};
    for(var i in foo) {
        if (foo.hasOwnProperty(i)) {
            console.log(i);
        }
    }

這是惟一正確的寫法,因爲咱們實用了 hasOwnProperty 方法,因此此次只輸出 moo。若是不適用 hasOwnProperty 方法,那麼當 Object.prototype 擴展時,就會出現錯誤。
如今不少框架都會選擇從 Object.prototype 擴展方法,因此咱們使用這些框架時,若是使用沒有用 hasOwnProperty 過濾的 for in 循環時就會遇到問題。api

總結

建議養成 hasOwnProperty 過濾屬性的好習慣,不要對運行環境作任何假設,也不管原生的原型對象是否被擴展。數組

參考

http://bonsaiden.github.io/JavaScript-Garden/#object.forinloopruby

相關文章
相關標籤/搜索