Когда ты используешь var в циклах, переменная имеет область видимости функции (или глобальную область видимости), что означает, что все итерации ссылаются на одну и ту же переменную. К тому времени, когда асинхронные коллбэки выполнятся, цикл уже завершился и переменная содержит своё финальное значение.
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100); // выведет 5, 5, 5, 5, 5
}
var не создаёт новую привязку на каждую итерациюsetTimeout замыкаются над одной и той же переменной ii уже достигла своего финального значения 5Решение 1: Используй let (предпочтительно)
Замени var на let, который имеет блочную область видимости и создаёт новую привязку для каждой итерации:
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100); // выведет 0, 1, 2, 3, 4
}
Решение 2: Используй IIFE-замыкание
Оберни коллбэк в немедленно вызываемое функциональное выражение (IIFE), чтобы захватить текущее значение i:
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(() => console.log(j), 100); // выведет 0, 1, 2, 3, 4
})(i);
}
let или const вместо var в современном JavaScriptlet устраняет этот класс багов, обеспечивая каждой итерации цикла её собственную независимую область видимостиКлючевое слово var в цикле создает новое связывание переменной для каждой итерации, поэтому все setTimeout callbacks выводят финальное значение цикла.
Новый — ещё не проверен сообществом
Вы