2013-04-12 48 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