Это очень распространенная проблема, с которой сталкиваются люди.
Проблема в том, что функция, которую вы передаете setTimeout
в каждой итерации, ссылается на такую же i
переменную.
JavaScript не имеет области видимости блока, только область действия функции. Таким образом, чтобы создать новую область видимости, которая сохранит желаемое значение i
, вам необходимо вызвать функцию внутри цикла, передав ей i
.
Пример: http://jsfiddle.net/GNwhR/3/
function set_up_timeout( j ) {
setTimeout(function(){
delayedLoad( j );
},3000*j);
}
function loadContent(){
var i,
len = 3
for (i = 0; i < len; i++) {
console.log(i);
set_up_timeout( i );
}
};
Это помещает ваш setTimeout
вызов в другую функцию, которая вызывается и передается i
в каждой итерации. Это создает новую область видимости переменной, где j
в функции ссылается на правильное значение.
Другой подход заключается в том, чтобы вызвать вызываемую функцию return a функцию:
Пример: http://jsfiddle.net/GNwhR/4/
function set_up_callback( j ) {
return function(){
delayedLoad( j );
};
}
function loadContent(){
var i,
len = 3
for (i = 0; i < len; i++) {
console.log(i);
setTimeout( set_up_callback( i ), 3000*i );
}
};
Этот вызывает set_up_callback
, что возвращает функцию, которая ссылается на j
.
Наконец, еще один распространенный подход - использовать IIFE (немедленно вызванное выражение функции) для устранения названной функции. Это менее понятно, ИМО:
Пример: http://jsfiddle.net/GNwhR/5/
function loadContent(){
var i,
len = 3
for (i = 0; i < len; i++) {
console.log(i);
setTimeout((function( j ){
return function() {
delayedLoad( j );
};
})( i ),3000*i);
}
};
Это в основном то же самое, что и предыдущий пример, в котором он возвращает функцию. Основное отличие состоит в том, что функция, которая возвращает функцию, создается и вызывается внутри самого цикла.
Все это иллюстрирует ту же концепцию, что вам нужно охватить переменную, если вы хотите позднее асинхронно ссылаться на нее и сохранить ее ожидаемое значение.