2014-02-18 96 views
0
var animel = new Array(); 

animel[0] = 'cat'; 
animel[1] = 'dog'; 
animel[2] = 'horse'; 
animel[3] = 'cow'; 
animel[4] = 'elephant'; 
animel[5] = 'tiger'; 
animel[6] = 'lion'; 
animel[7] = 'fish'; 

for (var i = 0; animel.length > i; i++) { 
    setTimeout(function() { 

     console.log(animel[i]); 

    }, 2000); 

} 

当我在控制台中执行此代码时,它会记录undefined而不是元素的名称。我在这做错了什么?为什么Array不能在控制台中工作?

+6

我不想编辑您的帖子对什么都没有,但它的** **的动物。该帖子的其余部分是:) – Lix

+1

animel [8]将始终未定义,计数器'i'在settimeout触发器时已经递增。 –

+1

在这个'动物'拼写错误和*所有*的答案是真的困扰我>。 nzifnab

回答

2

setTimeout中的功能引用相同的i值。所以对于每一个,i8

您需要创建一个闭包以“捕获”i值。

var createFunc = function(i){ 
    return function(){ 
     console.log(animel[i]); 
    }; 
}; 
for (var i = 0; animel.length > i; i++) { 
    setTimeout(createFunc(i), 2000); 
} 
2

这个数组没有问题,问题在于如何关闭变量i

当函数执行时(循环完成后2秒)i已经增加到animel的范围之外。最简单的办法是提供i当前值setTimeout并接受其作为函数的参数,就像这样:

for (var i = 0; animel.length > i; i++) { 
    setTimeout(function (i) { 
     console.log(animel[i]); 
    }, 2000, i); 
} 

如果需要支持IE < 9这句法中,MDN article提供了几个填充工具技术。

+0

为什么你通过'我''setTimeout'?那会做什么? –

+0

@RocketHazmat ['window.setTimeout'](https://developer.mozilla.org/en-US/docs/Web/API/Window.setTimeout)接受参数在执行时传递给函数。 –

+0

虽然浏览器不兼容,但显着的IE浏览器<9。 – deceze

0

你正在将它封装在一个非阻塞操作的setTimeout函数中。到循环完成时,我已经增加到一个打破循环并超出数组界限的值。

3

一个非常普遍的问题:回调是异步执行的,但使用最后一个设置值i。事件的链条是:

  • 你的循环设置了许多超时
  • 循环结束的,i的值是8
  • 超时火,并执行console.log(animel[i]),其中i8

为避免您需要将关闭连接中断至i

setTimeout((function (index) { 
    return function() { console.log(animel[index]); } 
})(i), 2000); 
+5

哇...这样的代码...所以括号...多关闭... – Lix

+2

(我(想)我是(一(Lisp((((开发人员))在)前)生活)) )。 – deceze

1

这是一个JS候选人。在setTimeout范围中使用的i的值不是您在使用时认为的值。为了在超时发生时强制使用i的实际值,可以使用i作为常量而不是迭代器的方式在其周围使用机箱。

for (var i = 0; i<animel.length; i++) { 
    (function(x){ 
     setTimeout(function() { 
      console.log(animel[x]); 
     }, 500); 
    })(i); 
} 

DEMO

相关问题