传递函数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; }