3 回答

TA貢獻1801條經驗 獲得超8個贊
不要for..in用于數組迭代。
重要的是要理解,[]用于訪問索引的Javascript數組的方括號語法()實際上是從Object... 繼承的。
obj.prop === obj['prop'] // true
該for..in結構不能像for..each/in其他語言(php,python等)中所看到的那樣更傳統。
Javascript for..in旨在迭代對象的屬性。產生每個屬性的密鑰。結合使用該鍵和Object的方括號語法,您可以輕松訪問所需的值。
var obj = {
foo: "bar",
fizz: "buzz",
moo: "muck"
};
for ( var prop in obj ) {
console.log(prop); // foo / fizz / moo
console.log(obj[prop]); // bar / buzz / muck
}
并且由于數組只是具有順序數字屬性名稱(索引)的對象,因此其for..in工作方式類似,因此產生數字索引的方式與生成上面的屬性名稱的方式相同。
該for..in結構的一個重要特征是,它將繼續在原型鏈中尋找可枚舉的屬性。它還將迭代繼承的可枚舉屬性。您有責任驗證當前屬性是否直接存在于本地對象上,而不是它所附加的原型是否存在于本地對象上hasOwnProperty()。
for ( var prop in obj ) {
if ( obj.hasOwnProperty(prop) ) {
// prop is actually obj's property (not inherited)
}
}
(有關原型繼承的更多信息)
for..in在Array類型上使用結構的問題在于,無法保證生成屬性的順序...而且通常來說,這是處理數組時極為重要的功能。
另一個問題是它通常比標準for實現慢。
底線
使用a for...in來迭代數組就像使用螺絲刀的but子釘釘子一樣...為什么不只使用錘子(for)?

TA貢獻1829條經驗 獲得超4個贊
for...in當您要遍歷對象的屬性時使用。但是它的作用與普通for循環相同:循環變量包含當前的“索引”,表示對象的屬性而不是值。
要遍歷數組,應使用常規for循環。buttons不是一個數組,而是一個NodeList(類似數組的結構)。
如果迭代buttons與for...in具有:
for(var i in a) {
console.log(i)
}
您將看到它輸出如下內容:
1
2
...
length
item
因為length和item是類型的對象的兩個屬性NodeList。因此,如果您天真地使用for..in,您將嘗試訪問buttons['length'].removeAttribute(),這將引發錯誤,因為buttons['length']它是函數而不是DOM元素。
因此正確的方法是使用普通for循環。但是還有另一個問題:
NodeLists處于活動狀態,這意味著每當您訪問時length,列表便會更新(再次搜索元素)。因此,您應該避免不必要的呼叫length。
例:
for(var i = 0, l = buttons.length; i < l, i++)

TA貢獻1836條經驗 獲得超13個贊
盡管for..in通常不應用于數組,但是在ES5之前,有一種將其與稀疏數組一起使用的情況。
如其他答案所述,for..in和Arrays的主要問題是:
屬性不一定按順序返回(即不是0、1、2等)。
返回所有可枚舉的屬性,包括非索引屬性和[[Prototype]]鏈上的那些屬性。這可能導致性能降低,因為可能需要hasOwnProperty測試來避免繼承屬性。
在ES5之前使用..的原因之一是使用稀疏數組可以提高性能,前提是順序無關緊要。例如,在下面:
var a = [0];
a[1000] = 1;
遍歷一個使用for..in會比使用for循環,因為它不僅可以訪問兩個屬性,而一個for循環將嘗試1001快得多。
但是,ES5的forEach使得這種情況變得多余,它僅訪問現有的成員,因此:
a.forEach();
還將僅依次迭代兩個屬性。
添加回答
舉報