Javascript 数组迭代陷阱

Javascript 数组迭代陷阱,javascript,Javascript,我总是得到意外输出的这段代码出了什么问题 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 var foo=[3,4,5]; for(foo中的变量i){ 如果(i==1){ foo.

我总是得到意外输出的这段代码出了什么问题

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
var foo=[3,4,5];
for(foo中的变量i){
如果(i==1){
foo.unshift(6,6);
}
文件。写入('item:'+foo[i]+“
”) } 输出: 项目:3 项目:6 项目:3


我能找到一个合适的理由吗?谢谢你,我在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:'+foo[i]+“
”)
i=0
您的
foo[0]
3
对于
i=1
unshift
之后的
foo==[6,6,3,4,5]
ie
foo[1]
6

  • 从中的…的摘要
for..in不应用于迭代索引顺序很重要的数组。
数组索引只是具有整数名称的可枚举属性,而不是
与一般对象属性相同。
无法保证for…in将以任何特定顺序返回索引,并返回所有可枚举属性, 包括非整数名称和继承的名称。

因为迭代的顺序取决于实现,所以在数组上迭代可能不会以一致的顺序访问元素。
因此,最好使用带有数字索引的for循环(或Array.forEach或非标准for…of循环)
在访问顺序很重要的数组上进行迭代时。

如果需要新属性
在枚举期间添加到要枚举的对象中,新添加的属性不保证
在活动枚举中被访问。在任何枚举中,属性名称的访问次数不得超过一次。

让我们举个例子,如果我们使用的是一个库,它使用

Array.prototype.maxLimit = 100000;
此属性在..的
上迭代。。在
循环中

要解释的代码的另一个版本。。在循环中

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 );    
}

警报
仅弹出一次

您在中使用的是而不是来迭代数组。这会导致JavaScript中出现各种各样的问题,您也遇到过这样的问题。由于中的
不保证任何特定的枚举顺序,因此它包含未移位的值。其他浏览器可能不包含它。。。这两个都是正确的。为什么我会情绪低落voted@amnotiam-有趣的是,只包含了一个新值,即使在IE中,我希望在最后看到这两个值。@RobG:是的,也许IE对数组的处理有点不同。。。特别是因为使用了
unshift
。@amnotiam IE通常会按属性添加的顺序返回属性,但它会在555k的帖子中给出结果,因为0在更改为6之前的值为3时已经被访问和写入,然后在写入项1之前将其更改为6,然后写入数组的其余部分。Fx不会访问最后2个成员,因为它们是在for..in循环启动后添加的。正如你所说,这两个结果都是一致的。第二项在哪里,即6它既不正确也不错误。实现将决定如何处理枚举期间添加的新属性,以及枚举的总体顺序。因为您使用的是IE:-),所以没有“正确”答案,因为使用的对象属性的迭代顺序取决于实现。正如您所展示的,在不同的实现中它确实是不同的。@RobG感谢您指出它依赖于实现。我只在IE中测试了它:-)。我在我的报告中加上了这一点answer@Maizere:什么有效?你难道不明白枚举的顺序是不能保证的吗?在某些情况下,浏览器可以决定完全更改顺序,这不会是一个bug。您的问题的真正答案是,不应像您正在使用它一样使用in的
。警报只会弹出一次,因为迭代语句中的表达式(即in运算符后括号中的位)只计算一次。
|
的LHS上的警报表达式的结果是未定义的值,其计算结果为false,因此foo被传递给操作符。我不明白这怎么能让OP更清楚。
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 );    
}