我有这个脚本:

for (var i = 1; i <= 2; i++) {
    setTimeout(function() { alert(i) }, 100);
}

但是3被提醒两次,而不是1和2。

有没有一种方法传递i,而不把函数写成字符串?


当前回答

好吧,另一个基于科迪的答案但更一般的解决方案是这样的:

function timedAlert(msg, timing){
    setTimeout(function(){
        alert(msg);    
    }, timing);
}

function yourFunction(time, counter){
    for (var i = 1; i <= counter; i++) {
        var msg = i, timing = i * time * 1000; //this is in seconds
        timedAlert (msg, timing);
    };
}

yourFunction(timeInSeconds, counter); // well here are the values of your choice.

其他回答

我也遇到过同样的问题这就是我解决的方法。

假设我想要12个间隔为2秒的延迟

    function animate(i){
         myVar=setTimeout(function(){
            alert(i);
            if(i==12){
              clearTimeout(myVar);
              return;
            }
           animate(i+1)
         },2000)
    }

    var i=1; //i is the start point 1 to 12 that is
    animate(i); //1,2,3,4..12 will be alerted with 2 sec delay

这是因为!

超时函数 回调在循环完成后都运行良好。事实上, 作为计时器,即使它是setTimeout(.., 0),所有 这些函数回调在完成后仍然严格运行 这就是为什么有3个被反射了! 这两个函数都有定义 在每个循环迭代中,分别在相同的共享全局上关闭 范围,实际上只有一个I在里面。

解决方案通过使用执行的自我函数(匿名或更好的IIFE)来声明每个迭代的单一作用域,并在其中有一个i的副本,如下所示:

for (var i = 1; i <= 2; i++) {

     (function(){

         var j = i;
         setTimeout(function() { console.log(j) }, 100);

     })();

}

更干净的一个

for (var i = 1; i <= 2; i++) {

     (function(i){ 

         setTimeout(function() { console.log(i) }, 100);

     })(i);

}

在每个迭代中使用IIFE(自执行函数)为每个迭代创建了一个新的作用域 迭代,这给了我们的超时函数回调机会 为每个迭代关闭一个具有变量的新作用域 有正确的每次迭代值供我们访问。

真正的解决方案在这里,但是您需要熟悉PHP编程语言。 你必须混合使用PHP和JAVASCRIPT才能达到你的目的。

请注意:

<?php 
for($i=1;$i<=3;$i++){
echo "<script language='javascript' >
setTimeout(function(){alert('".$i."');},3000);  
</script>";
}
?> 

它完全是你想要的,但要小心如何使之间的关系 PHP变量和JAVASCRIPT变量。

你可以使用立即调用的函数表达式(IIFE)来创建一个围绕setTimeout的闭包:

for (var i = 1; i <= 3; i++) { (函数(索引) { setTimeout(function() { alert(index); }, i * 1000); })(i); }

你可以使用bind方法

for (var i = 1, j = 1; i <= 3; i++, j++) {
    setTimeout(function() {
        alert(this);
    }.bind(i), j * 100);
}