猿问
下载APP

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

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

我正在尝试使用setTimeout来执行我传递信息的匿名函数,我遇到了麻烦。这个(硬编码版本)可以正常工作:

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

但是我试图从数组中取出hello和world并将它们传递给函数,而不是(a)使用全局变量,以及(2)使用eval。我知道如何使用全局或eval来做到这一点,但是如何在没有它的情况下做到这一点。这是我想做的(但我知道它不会起作用):

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

当然,字符串[i]将脱离上下文。如何在没有eval或globals的情况下将字符串[i]传递给该匿名函数?


幕布斯6054654
浏览 31回答 3
3回答

胡子哥哥

这是经常重复的“如何在闭包中使用循环变量”问题。规范的解决方案是调用一个函数,该函数返回一个绑定到循环变量当前值的函数:var&nbsp;strings&nbsp;=&nbsp;[&nbsp;"hello",&nbsp;"world"&nbsp;];var&nbsp;delay&nbsp;=&nbsp;1000;for(var&nbsp;i=0;i<strings.length;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;setTimeout( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(function(s)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;function()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;alert(s); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;})(strings[i]),&nbsp;delay); &nbsp;&nbsp;&nbsp;&nbsp;delay&nbsp;+=&nbsp;1000;}外部定义function(s) { ... }创建一个新的作用域,其中s绑定到所提供参数的当前值 - 即strings[i]-&nbsp;内部作用域可用的位置。

撒科打诨

只需在setTimeout调用周围添加一个范围:var&nbsp;strings&nbsp;=&nbsp;[&nbsp;"hello",&nbsp;"world"&nbsp;];var&nbsp;delay&nbsp;=&nbsp;1000;for(var&nbsp;i=0;i<strings.length;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;(function(s){ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;setTimeout(&nbsp;function(){alert(s);},&nbsp;delay); &nbsp;&nbsp;&nbsp;&nbsp;})(strings[i]); &nbsp;&nbsp;&nbsp;&nbsp;delay&nbsp;+=&nbsp;1000;}

三国纷争

您可以编写一个单独的函数来设置超时:function&nbsp;doTimer(str,&nbsp;delay)&nbsp;{ &nbsp;&nbsp;setTimeout(function()&nbsp;{&nbsp;alert(str);&nbsp;},&nbsp;delay);}然后从循环中调用它:var&nbsp;delay&nbsp;=&nbsp;1000;for(var&nbsp;i=0;i<strings.length;i++)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;doTimer(strings[i],&nbsp;delay); &nbsp;&nbsp;&nbsp;&nbsp;delay&nbsp;+=&nbsp;1000;}
打开App,查看更多内容
随时随地看视频慕课网APP
我要回答