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 loop は 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 に答える