Есть setTimeout
внутри цикла for
:
for (var i = 1; i <= 5; i++) {
setTimeout(function() {
alert(i);
}, i * 1000);
}
Я хочу показывать числа 1
, 2
, 3
, 4
, 5
, но показывает 6
, 6
, 6
, 6
, 6
. Почему?
Дело в том, что функция выполняается после того, что цикл закончится. Поэтому, i
уже равно 6
, когда alert(i)
выполняется первый раз.
Если еще непонятно, вот похожий пример в псевдокоде:
У меня 1 камень.
Через минуту скажи, сколько у меня камней.
Дай мне камень сейчас.
Через 2 минуты скажи, сколько у меня камней.
Дай мне камень сейчас.
Получится, что сейчас мне даст 2 камня, в итоге у меня будут 3. Через минуту скажет, сколько у меня камней (т.е. 3), и через две минуты опять скажет, что у меня 3 камня.
i
функцией alert
каждая итерация. Это самое обычное решение. for(var i = 1; i <= 5; i++) {
(function(i) {
setTimeout(function() {
alert(i);
}, i * 1000);
})(i);
}
Создавать много одинаковых функций - не очень хорошо, можно поднять эту функцию выше:
function pass(i) {
return function () {
alert(i);
}
}
for(var i = 1; i <= 5; i++) {
setTimeout(pass(i), i * 1000);
}
(function f(i) {
if (i > 5) return;
setTimeout(function() {
alert(i);
f(i + 1);
}, 1000);
})(1);
Function.prototype.bind()
, чтобы создать новую функцию каждая итерация. Это короче первого варианта, но IE8 и ниже не поддерживают .bind
.for (var i = 1; i <= 5; i++) {
setTimeout(function(i) {
alert(i);
}.bind(null, i), i * 1000);
}
setTimeout
. Это поддерживают все современные браузеры, но если речь идёт о старых, то стоит проверить.for(var i = 1; i <= 5; i++) {
setTimeout(function (i) {
alert(i);
}, i * 1000, i);
}
Замечу, что теперь функции в цикле ничем не отличаются друг от друга, поэтому можно сделать одну функцию:
function doSmth(i) {
alert(i);
}
for(var i = 1; i <= 5; i++) {
setTimeout(doSmth, i * 1000, i);
}
let
(простите, не нашел документацию на русском). Это удобный вариант, но это новая возможность в ECMAScript 2015, так что еще не работает в большинстве браузеров. Если хотите использовать ECMAScript 2015 до того, что браузеры его поддерживают, рекомендую попробовать Babel.for (let i = 1; i <= 5; i++) {
setTimeout(function() {
alert(i);
}, i * 1000);
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Добрый деньЕсть код на js, который сворачивает/разворачивает текст статей