传递函数setTimeout在循环中:总是最后一个值?

我试图使用setTimeout来执行一个匿名函数,我传递的信息,我有麻烦。 这(硬编码版本)将工作得很好:

setTimeout(function(){alert("hello");},1000); setTimeout(function(){alert("world");},2000); 

但是我试图从数组中取出hello和world,并且不用(a)使用全局variables将它们传递给函数,(2)使用eval。 我知道如何使用全局variables或eval来做到这一点,但是我怎样才能做到这一点。 这是我想做的事情(但我知道这是行不通的):

 var strings = [ "hello", "world" ]; var delay = 1000; for(var i=0;i<strings.length;i++) { setTimeout( function(){alert(strings[i]);}, delay); delay += 1000; } 

当然,string[i]将脱离上下文。 如何将string[i]传递给匿名函数而不用eval或全局variables?

这是经常重复的“如何在闭包中使用循环variables”问题。

规范的解决scheme是调用一个函数,该函数返回一个绑定到循环variables当前值的函数:

 var strings = [ "hello", "world" ]; var delay = 1000; for(var i=0;i<strings.length;i++) { setTimeout( (function(s) { return function() { alert(s); } })(strings[i]), delay); delay += 1000; } 

外部定义function(s) { ... }创build一个新的作用域,其中s被绑定到所提供的参数的当前值 – 即strings[i] – 它可用于内部作用域。

只需在setTimeout调用周围添加一个范围:

 var strings = [ "hello", "world" ]; var delay = 1000; for(var i=0;i<strings.length;i++) { (function(s){ setTimeout( function(){alert(s);}, delay); })(strings[i]); delay += 1000; } 

您可以编写一个单独的函数来设置超时:

 function doTimer(str, delay) { setTimeout(function() { alert(str); }, delay); } 

然后从循环中调用它:

 var delay = 1000; for(var i=0;i<strings.length;i++) { doTimer(strings[i], delay); delay += 1000; } 

尽pipe不像其他一些答案那样向后兼容,但是我以为我会抛出另一个选项。这次使用bind() !

 var strings = [ "hello", "world" ]; var delay = 1000; for(var i=0;i<strings.length;i++) { setTimeout(alert.bind(this, strings[i]), delay); delay += 1000; } 

查看它的行动演示

 var strings = [ "hello", "world" ]; var delay = 1000; for(var i=0;i<strings.length;i++) { setTimeout( new Function('alert(strings[i]);'), delay); delay += 1000; }