和 in 操作符一樣,for in 循環(huán)同樣在查找對象屬性時遍歷原型鏈上的所有屬性。
注意:
for in循環(huán)不會遍歷那些enumerable設(shè)置為false的屬性;比如數(shù)組的length屬性。
// 修改 Object.prototype
Object.prototype.bar = 1;
var foo = {moo: 2};
for(var i in foo) {
console.log(i); // 輸出兩個屬性:bar 和 moo
}
由于不可能改變 for in 自身的行為,因此有必要過濾出那些不希望出現(xiàn)在循環(huán)體中的屬性,
這可以通過 Object.prototype 原型上的hasOwnProperty函數(shù)來完成。
注意: 由于
for in總是要遍歷整個原型鏈,因此如果一個對象的繼承層次太深的話會影響性能。
// foo 變量是上例中的
for(var i in foo) {
if (foo.hasOwnProperty(i)) {
console.log(i);
}
}
這個版本的代碼是唯一正確的寫法。由于我們使用了 hasOwnProperty,所以這次只輸出 moo。
如果不使用 hasOwnProperty,則這段代碼在原生對象原型(比如 Object.prototype)被擴展時可能會出錯。
一個廣泛使用的類庫 Prototype 就擴展了原生的 JavaScript 對象。
因此,當(dāng)這個類庫被包含在頁面中時,不使用 hasOwnProperty 過濾的 for in 循環(huán)難免會出問題。
推薦總是使用 hasOwnProperty。不要對代碼運行的環(huán)境做任何假設(shè),不要假設(shè)原生對象是否已經(jīng)被擴展了。