13

考虑以下示例:

var cb = function (t) {
    console.log('callback -->' + t);
};

for(var i = 0; i<3; i++) {
    console.log(i);
    setTimeout(function(){
        cb(i);
    },1000);
}

jsfiddle 的工作示例

此代码段的输出是:

0
1
2
callback ---> 3
callback ---> 3
callback ---> 3

一切都按预期工作,for 循环将 3 个回调调用放入事件循环中。在 for 循环结束时 i == 3 并且当回调被执行时,它们都会打印 3,因为它们包含指向 i 的链接,即 3。如何改进此代码段,以便在执行回调时使用实际传递给它的值。

输出应该是:

callback ---> 1
callback ---> 2
callback ---> 3

提前致谢。

4

4 回答 4

18

创建一个闭包,以便setTimeout处理程序引用闭包的局部变量(在这种情况下,我们也将其命名为i),而不是i来自循环:

for (var i = 0; i < 3; i++) {
    (function (i) {
        console.log(i);
        setTimeout(function () {
            cb(i);
        }, 1000);
    }(i));
}
于 2013-04-29T09:55:36.133 回答
6

你可以试试.bind

for(var i = 0; i<3; i++) {
    console.log(i);
    setTimeout(cb.bind(null, i),1000);
}

演示。

处理这个问题的传统方法是创建一个闭包:

for(var i = 0; i<3; i++) {
    console.log(i);
    setTimeout((function(i){return function(){cb(i)}}(i)),1000);
}
于 2013-04-29T09:55:30.897 回答
3

一个常见的问题。让我们尝试使用 JS 未来的一些特性。我的意思是。它创建局部范围变量,您不需要使用闭包或其他技巧。但现在它只适用于 FF(我使用的是 20.0.1)

for(var i = 0; i<3; i++) {
    console.log(i);
    let a = i;
    setTimeout(function(){               
        cb(a);
    },1000);
}
于 2013-04-29T10:15:38.003 回答
1

我只会setTimeout()在你的 cb 的功能中使用

var cb = function (t) {
  setTimeout(function(){
    console.log('callback -->' + t);
  },1000);
};


for(var i = 0; i<3; i++) {
    console.log(i);
        cb(i);
}
于 2013-04-29T09:57:00.793 回答