我有这个脚本:

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

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

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


当前回答

答案?

我用它来做一个添加物品到购物车的动画——当点击产品“添加”按钮时,一个购物车图标浮动到购物车区域:

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

时间单位为单位乘以n周期。

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

epoc: https://en.wikipedia.org/wiki/Epoch_ (reference_date)

希望这能有所帮助!

其他回答

答案?

我用它来做一个添加物品到购物车的动画——当点击产品“添加”按钮时,一个购物车图标浮动到购物车区域:

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

时间单位为单位乘以n周期。

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

epoc: https://en.wikipedia.org/wiki/Epoch_ (reference_date)

希望这能有所帮助!

这是因为!

超时函数 回调在循环完成后都运行良好。事实上, 作为计时器,即使它是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(自执行函数)为每个迭代创建了一个新的作用域 迭代,这给了我们的超时函数回调机会 为每个迭代关闭一个具有变量的新作用域 有正确的每次迭代值供我们访问。

你可以使用立即调用的函数表达式(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);
}

setTimeout的函数参数在循环变量上关闭。循环在第一个超时之前结束,并显示当前值i,即3。

因为JavaScript变量只有函数作用域,解决方案是将循环变量传递给设置超时的函数。你可以像这样声明和调用这样的函数:

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