如同 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
的奠定石。這裏不作詳細介紹,詳細內容能夠參考 - Enumerable。git
因爲咱們無法改變 for in
循環自己的行爲,因此咱們只能採起其餘方法來過濾掉那些不但願出如今循環內的屬性,經過 《細說 Javascript 對象篇(三) : hasOwnProperty》 咱們知道 hasOwnProperty
方法是能夠作到這一點的。github
仍然使用上個例子: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