2021 アップデート
var
変数を宣言する唯一の方法でした。しかし、現在、この問題をより良い方法で解決するconst
とがあります。let
これらの変数宣言は、バインド先のスコープとしてループを尊重します。つまり、次のスニペットは正常に機能し、これらの値をキャプチャする匿名関数は必要ありません。
const colors = ['green', 'blue', 'red'];
for (let i = 0; i < colors.length; i++) {
const color = colors[i];
setTimeout(function() {
alert(color);
}, i * 1000);
}
以下は、この質問に対する 2012 年の最初の回答です。
ループの一部として、すぐには実行されない内部関数がある場合。
var i, colors = ['green', 'blue', 'red'];
for (i = 0; i < colors.length; i++) {
var color = colors[i];
setTimeout(function() {
alert(color);
}, i * 1000);
}
// red
// red
// red
ループの中にありvar color
ますが、ループにはスコープがありません。実際には、すべてのループ反復で使用される変数は 1 つだけです。そのため、タイムアウトが発生すると、それらはすべて同じ値、つまりループによって設定された最後の値を使用します。
var i, colors = ['green', 'blue', 'red'];
for (i = 0; i < colors.length; i++) {
(function(color) {
setTimeout(function() {
alert(color);
}, i * 1000);
})(colors[i]);
}
// green
// blue
// red
これは、各反復で値を関数の引数にキャプチャし、スコープを作成します。color
これで、各関数は、そのループ内で作成された関数が後で実行されたときに変更されない独自のバージョンの変数を取得します。