Этот код выводит в консоль 3 3 3 через 1 секунду, вместо ожидаемого 0 1 2.
Корень проблемы — область видимости var. Когда используется var, существует только один общий экземпляр переменной i на весь цикл. Каждый колбэк в setTimeout захватывает ссылку на эту же переменную — не её значение в момент итерации.
К моменту выполнения колбэков (через 1000мс) цикл уже завершился, а i увеличилась до финального значения 3. Все три колбэка логируют это же значение.
Вариант 1 — использовать let (рекомендуется):
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 1000);
}
let имеет блочную область видимости, поэтому каждая итерация создаёт свою собственную привязку i. Результат: 0 1 2.
Вариант 2 — использовать IIFE для захвата значения:
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 1000);
})(i);
}
IIFE (Immediately Invoked Function Expression) создаёт новую область видимости функции на каждой итерации, передавая текущее значение i как аргумент j. Это фиксирует значение в этот момент времени.
var создаёт одну общую ссылку на все итерации циклаlet создаёт новую привязку для каждой итерации, что является предпочтительным современным решениемlet недоступенКогда ты используешь var в цикле с setTimeout, каждый callback захватывает ссылку на ту же переменную, а не сохраняет значение на момент итерации.
Новый — ещё не проверен сообществом
Вы