for循环中的setTimeout不会打印连续值[重复]

2020/10/07 17:21 · javascript ·  · 0评论

我有这个脚本:

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

3被警告两次,而不是1那么2

有没有一种方法可以传递i而不将函数编写为字符串?

您必须为每个超时功能安排一个明显的“ i”副本。

function doSetTimeout(i) {
  setTimeout(function() { alert(i); }, 100);
}

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

如果您不做这样的事情(同一想法还有其他变体),那么每个计时器处理程序函数将共享相同的变量“ i”。循环结束后,“ i”的值是多少?3!通过使用中间函数,可以复制变量的值。由于超时处理程序是在该副本的上下文中创建的,因此它具有自己的专用“ i”。

编辑-随着时间的流逝,出现了一些评论,由于设置了一些超时会导致处理程序同时触发所有事实,因此有些混乱显而易见。重要的是要了解,设置计时器的过程-调用setTimeout()-几乎不需要时间。也就是说,告诉系统“请在1000毫秒后调用此函数”将几乎立即返回,因为在计时器队列中安装超时请求的过程非常快。

因此,如果进行了一系列超时请求(如OP中的代码和我的答案中的情况),并且每个时间延迟值都相同,那么一旦经过该时间量,所有计时器处理程序将会迅速相继被称为。

如果您需要按间隔调用处理程序,则可以使用setInterval(),它的调用方式与完全相同,setTimeout()但是在重复请求数量的延迟后将触发多次,或者您可以建立超时并乘以时间您的迭代计数器的价值。也就是说,修改我的示例代码:

function doScaledTimeout(i) {
  setTimeout(function() {
    alert(i);
  }, i * 5000);
}

(如果100超时时间毫秒,效果将不会很明显,因此我将该数字提高到5000。)该值i乘以基本延迟值,因此在循环中调用5次将导致5次延迟。秒,10秒,15秒,20秒和25秒。

更新资料

在2018年,这里有一个更简单的选择。由于具有在比函数更狭窄的范围内声明变量的新功能,因此,如果修改了原始代码,则可以工作:

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

let声明,不像var,本身就会造成那里是一个独特i的循环的每个迭代。

您可以使用立即调用的函数表达式(IIFE)在以下位置创建一个闭包setTimeout

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

这是因为

  1. 超时循环完成后函数回调都运行良好。实际上,随着计时器的运行,即使每次迭代都设置为setTimeout(..,0),所有这些函数回调仍将严格在循环完成后运行,这就是为什么要反映3的原因!
  2. 尽管这两个函数在每个循环迭代中都是分别定义的,但它们在同一共享全局范围(实际上只有一个i)上是封闭的

解决方案的通过使用执行的自功能(匿名一个或更好声明对于每次迭代单个范围IIFE)与具有的副本在里面,这样的:

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(自执行函数)都会为每次迭代创建一个新的作用域,这使我们的超时函数回调有机会为每次迭代关闭一个新的作用域,即每个变量具有正确的-供我们访问的迭代值。

的function参数setTimeout关闭了循环变量。循环的第一超时而显示的当前值之前完成i,这是3

由于JavaScript变量仅具有函数作用域,因此解决方案是将循环变量传递给设置超时的函数。您可以声明并调用这样的函数:

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

您可以使用额外的参数setTimeout来将参数传递给回调函数。

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

注意:此功能不适用于IE9及以下版本的浏览器。

答案

我将其用于将商品添加到购物车的动画-点击后,购物车图标会从产品“添加”按钮浮动到购物车区域:

function addCartItem(opts) {
    for (var i=0; i<opts.qty; i++) {
        setTimeout(function() {
            console.log('ADDED ONE!');
        }, 1000*i);
    }
};

注意持续时间以单位乘以n epocs单位

因此,从点击时刻开始,动画(EACH动画的)开始epoc是每个一秒单位乘以项目数的乘积。

epochttps : //en.wikipedia.org/wiki/Epoch_(参考日期

希望这可以帮助!

你可以使用bind方法

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

好吧,另一个基于科迪答案的可行解决方案,但更通用一些,可以是这样的:

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

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

注意这一点:

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

它确实可以满足您的要求,但是要注意如何在PHP变量和JAVASCRIPT变量之间进行分配。

本文地址:http://javascript.askforanswer.com/forxunhuanzhongdesettimeoutbuhuidayinlianxuzhizhongfu.html
文章标签:
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!