JavaScript的for…in迴圈用於迭代訪問物件中的可列舉(enumerable)屬性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var tMinus = { two: "Two", one: "One", zero: "Blast off!" }; var countdown = ""; for (var step in tMinus) { countdown += tMinus[step] + "n"; } console.log(countdown); // => "Two // One // Blast Off! // " |
因為for…in迴圈支援所有的JavaScript物件,所以它同樣可用於陣列物件之中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var tMinus = [ "Two", "One", "Blast off!" ]; var countdown = ""; for (var step in tMinus) { countdown += tMinus[step] + "n"; } console.log(countdown); // => "Two // One // Blast Off! // " |
然而,以這樣的方式遍歷陣列存在三個問題。首先,for…in迴圈會遍歷陣列物件的原型鏈中所有的可列舉屬性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Array.prototype.voice = "James Earl Jones"; var tMinus = [ "Two", "One", "Blast off!" ]; var countdown = ""; for (var step in tMinus) { countdown += tMinus[step] + "n"; } console.log(countdown); // => "Two // One // Blast Off! // James Earl Jones // " |
不過,我們可以藉助hasOwnProperty函式來避免這一問題:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
Array.prototype.voice = "James Earl Jones"; var tMinus = [ "Two", "One", "Blast off!" ]; var countdown = ""; for (var step in tMinus) { if (tMinus.hasOwnProperty(step)) { countdown += tMinus[step] + "n"; } } console.log(countdown); // => "Two // One // Blast Off! // " |
此外,在ECMAScript5.1規範中提到,for…in迴圈可能以任意順序來遍歷物件的屬性。
對於無序的普通物件來說,屬性的訪問順序無關緊要。但有時候你可能不想Javascript engine以隨機順序處理你的陣列元素,因為它會導致不可預知的結果:
1 2 3 4 5 |
console.log(countdown); // => "Blast Off! // One // Two // " |
最後,for…in迴圈除了訪問陣列元素以外,還會訪問其它的可遍歷屬性。正如我們在之前的文章所提到的,我們可以向陣列變數新增額外的屬性。而這樣的操作同樣會導致不可預知的後果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
var tMinus = [ "Two", "One", "Blast off!" ]; tMinus.announcer = "Morgan Freeman"; var countdown = ""; for (var step in tMinus) { if (tMinus.hasOwnProperty(step)) { countdown += tMinus[step] + "n"; } } console.log(countdown); // => "Two // One // Blast Off! // Morgan Freeman // " |
由此可見,當你需要遍歷陣列元素的時候,應使用for迴圈或者陣列物件的內建迭代函式(如forEach、map等),而不是for…in迴圈。