for...in主要用於對數組和對象的屬性進行遍歷。for ... in 迴圈中的代碼每執行一次,就會對數組的元素或者對象的屬性進行一次操作。 語法:for (variable in object) {...} 對數組操作 可以發現在for in函數中變數以字元串的形式出現,這時候在函數中操作a[x ...
for...in主要用於對數組和對象的屬性進行遍歷。for ... in 迴圈中的代碼每執行一次,就會對數組的元素或者對象的屬性進行一次操作。
語法:for (variable in object) {...}
variable:
每次迭代,一個不同的屬性名將會賦予variable。object:
可枚舉屬性被迭代的對象。
對數組操作
var a=[5,4,3,2,1]; var x=0; console.log(typeof x);//number for (x in a) { console.log("a["+x+"]: "+a[x]); console.log(typeof x);//string } console.log(x);//4 console.log(typeof x);//string //output: // a[0]: 5 // a[1]: 4 // a[2]: 3 // a[3]: 2 // a[4]: 1
可以發現在for in函數中變數以字元串的形式出現,這時候在函數中操作a[x+1]的話是無效的,x+1會進行字元串拼接。
對象操作
var obj={"1":"first", "two":"zoo", "3":"2", "three":"34", "4":"1", "2":"second" }; for (var i in obj) { console.log(i+":"+obj[i]); }; //output: //1:first //2:second //3:2 //4:1 //two:zoo //three:34
可發現,for...in 並不能夠保證返回的是按一定順序的索引,但是它會返回所有可枚舉屬性,包括繼承屬性。
給原型添加屬性之後,預設情況下枚舉,會把原型屬性一併輸出,如下所示。由於它總是會訪問該對象的原型,看下原型上是否有屬性,這在無意中就給遍歷增加了額外的壓力。
例:
function fun4(){ var a=[1,2,3,4,5]; Array.prototype.age=13; for(var i in a){ console.log("a["+i+"]: "+a[i]); } } //outuput: //a[0]: 1 //a[1]: 2 //a[2]: 3 //a[3]: 4 //a[4]: 5 //a[age]: 13
解決方法:
如果你只要考慮對象本身的屬性,而不是它的原型,那麼使用 getOwnPropertyNames()
或執行 hasOwnProperty()
來確定某屬性是否是對象本身的屬性 (也能使用propertyIsEnumerable
)。
下麵利用 hasOwnProperty()
的方法使隱藏的繼承屬性不會被顯示。如果該對象是從原型鏈中繼承了該屬性,或者根本沒有這樣的一個屬性,則返回false。如果某個對象具有給定名稱的屬性,則返回true。
function fun4(){ var a=[1,2,3,4,5]; Array.prototype.age=13; for(var i in a){ if( a.hasOwnProperty( i ) ) { console.log("a["+i+"]: "+a[i]); } } } //outuput: //a[0]: 1 //a[1]: 2 //a[2]: 3 //a[3]: 4 //a[4]: 5
在迭代進行時被添加到對象的屬性,可能在之後的迭代被訪問,也可能被忽略。通常,在迭代過程中最好不要在對象上進行添加、修改或者刪除屬性的操作,除非是對當前正在被訪問的屬性。這裡並不保證是否一個被添加的屬性在迭代過程中會被訪問到,不保證一個修改後的屬性(除非是正在被訪問的)會在修改前或者修改後被訪問,不保證一個被刪除的屬性將會在它被刪除之前被訪問。
Note: 意思就是儘量不要對數組對象使用for in遍歷。