2013-04-12 46 views
3

這段代碼中出現了什麼問題,我總是得到意外的輸出?數組迭代陷阱

var foo = [3,4,5]; 

for (var i in foo) { 
     if (i == 1) { 
    foo.unshift(6,6); 
     } 
    document.write('item: '+foo[i]+"<br>") 
    } 
output: 
item: 3 
item: 6 
item: 3 

我能得到這個一個合適的理由?感謝ü

+2

使用了'換in'迭代您的陣列,而不是'for'。這導致了JavaScript中的各種問題,並且您遇到了一個問題。由於'for-in'不能保證枚舉的任何特定順序,因此它包含未轉移的值。一個不同的瀏覽器可能不包括它......並且這兩個都是正確的。 – 2013-04-12 05:19:29

+0

爲什麼我會選擇 –

+0

@ amnotiam,儘管只有一個新值被包括在內,即使在IE中,我期望在最後看到這兩個值。 – RobG

回答

1

IE8得到的輸出是這

item: 3 
item: 6 
item: 3 
item: 4 
item: 5 

這是正確的。如果你想在unshift使用後全面更新值另一個循環

var foo = [3,4,5]; 
    for (var i in foo) { 
     if (i == 1) { 
    foo.unshift(6,6); 
     } 
    } 
    for (var i in foo) 
    document.write('item: '+foo[i]+"<br>") 

哪位能給

item: 6 
item: 6 
item: 3 
item: 5 
item: 4 

在你的代碼,當你調用document.write('item: '+foo[i]+"<br>")i = 0foo[0]3 對於i=1unshiftfoo == [6,6,3,4,5]foo[1]後是6

+0

哪裏是第二個項目,即6 –

+1

這既不正確也不正確。實現可以決定如何處理在枚舉期間添加的新屬性以及枚舉的整體順序。 – 2013-04-12 05:40:52

+1

因爲你使用IE。 :-)由於使用[for..in](http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.4)對對象屬性進行迭代的順序,沒有「正確的」答案)是依賴於實現的。正如你已經表明的那樣,它在不同的實現中**是**不同的。 – RobG

0

for..in should not be used to iterate over an Array where index order is important. Array indexes are just enumerable properties with integer names and are otherwise identical to general Object properties.
There is no guarantee that for...in will return the indexes in any particular order and it will return all enumerable properties, including those with non–integer names and those that are inherited.

Because the order of iteration is implementation dependent, iterating over an array may not visit elements in a consistent order. Therefore it is better to use a for loop with a numeric index (or Array.forEach or the non-standard for...of loop) when iterating over arrays where the order of access is important.

If new properties are added to the object being enumerated during enumeration, the newly added properties are not guaranteed to be visited in the active enumeration. A property name must not be visited more than once in any enumeration.

讓我們來討論一下例子,如果我們正在使用一個庫,它使用。

Array.prototype.maxLimit = 100000; 

該屬性遍歷for .. in循環。

代碼的另一個版本來解釋for .. in循環

var foo = [3,4,5]; 

for (var i in (alert(JSON.stringify(foo)) || foo)) { 

    if (i == 1) { 
     foo.unshift(6,6); 
    } 
    console.log('item: '+foo[i] , i , foo.length);  
} 

alert彈出只有一次

+0

此警報僅彈出一次,因爲迭代語句中的表達式(即* in *運算符後的括號內的位)僅計算一次。 「||」的LHS上的警報表達式的結果是未定義的值,它的計算結果爲false,所以* foo *被傳遞給運算符。我不明白這是如何讓OP更清晰的。 – RobG