Почему в цикле for с var и setTimeout всегда печатается одно и то же число?
Запускаю такой код и ожидаю 0,1,2,3,4, а в консоли пять раз подряд 5. Что не так?
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100);
}
3 ответа
Тут два эффекта сразу: замыкание + область видимости var.
var i — одна-единственная переменная на весь цикл (она функциональной области видимости, не блочной). Все пять колбэков setTimeout запоминают ссылку на одну и ту же i. Колбэки выполняются позже, когда цикл уже закончился и i стало равно 5. Поэтому печатается пять раз 5.
Самое простое решение — заменить var на let:
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100); // 0,1,2,3,4
}
let в цикле for создаёт новую переменную на каждой итерации, и каждый колбэк замыкается на свою копию i. Старый способ (до ES6) — обернуть в IIFE и передать i параметром, но сейчас let решает всё в одну строку.
Замени var на let. С var переменная одна на весь цикл, и к моменту срабатывания таймеров она уже равна 5. let создаёт свою i на каждой итерации.
Замени var на let.