8 Окт 2025 в 11:36
21 +1
0
Ответы
1

Кратко — почему выводится 3 три раза:

Исходный код
for (var i = 0; i < 3; i++) {
setTimeout(function() { console.log(i); }, 100);
}

1) Переменная i объявлена через var — она имеет функциональную (или глобальную) область видимости, не блоковую. То есть внутри цикла используется одна и та же переменная i.
2) setTimeout ставит функцию в очередь на выполнение позже (асинхронно). Когда таймеры срабатывают, цикл уже закончился и значение i стало 3.
3) Колбэки замыкают (closure) саму переменную i, а не её значение на каждой итерации. Поэтому все три колбэка читают текущее (на момент выполнения) значение i = 3.

Как исправить (несколько разных способов). Все эти варианты приведут к выводу 0, 1, 2.

1) Использовать let в заголовке цикла (ES6)
for (let i = 0; i < 3; i++) {
setTimeout(function() { console.log(i); }, 100);
}
Пояснение: let создаёт новую привязку i для каждой итерации (блоковая область), замыкание захватывает именно эту привязку.

2) Замыкание через IIFE (самовызывающаяся функция) — работает в старых окружениях
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(function() { console.log(j); }, 100);
})(i);
}
Пояснение: в параметре j сохраняется текущее значение i, и колбэк замыкает j — оно не изменится.

3) Фабрика функции (явно создать замыкание)
function makeLogger(x) {
return function() { console.log(x); };
}
for (var i = 0; i < 3; i++) {
setTimeout(makeLogger(i), 100);
}
Пояснение: makeLogger захватывает значение x и возвращает функцию, которая его использует.

4) Передать аргумент в setTimeout (поддерживается в браузерах и Node)
for (var i = 0; i < 3; i++) {
setTimeout(function(x) { console.log(x); }, 100, i);
}
Пояснение: setTimeout позволяет передать дополнительные аргументы, которые пойдут в колбэк при вызове — там передаётся текущее значение i.

5) Использовать bind для «захвата» значения
for (var i = 0; i < 3; i++) {
setTimeout(console.log.bind(null, i), 100);
}
Пояснение: bind создаёт функцию с уже привязанным аргументом i (текущее значение), поэтому при выполнении будет напечатано это значение.

Любой из этих подходов исправит поведение и выведет 0, 1, 2.

8 Окт 2025 в 12:12
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир