for...in主要用於對數組和對象的屬性進行遍歷。for ... in 循環中的代碼每執行一次,就會對數組的元素或者對象的屬性進行一次操做。數組
語法:for (variable in object) {...}函數
variable:
每次迭代,一個不一樣的屬性名將會賦予
variable。
object:
可枚舉屬性被迭代的對象。
對數組操做spa
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會進行字符串拼接。prototype
對象操做code
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 並不可以保證返回的是按必定順序的索引,可是它會返回全部可枚舉屬性,包括繼承屬性。對象
給原型添加屬性以後,默認狀況下枚舉,會把原型屬性一併輸出,以下所示。因爲它老是會訪問該對象的原型,看下原型上是否有屬性,這在無心中就給遍歷增長了額外的壓力。blog
例:繼承
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
)。three
下面利用 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遍歷。