В чём проблема этого JavaScript‑фрагмента и как её исправить: for (var i = 0; i console.log(i), 100); } — объясните ожидаемый и фактический вывод и предложите несколько корректных решений

12 Ноя 2025 в 10:17
24 +1
0
Ответы
1
Проблема: переменная `i` объявлена через `var`, она имеет функциональную (не блочную) область видимости. Колбэки в `setTimeout` замыкают одну и ту же переменную `i`, и к моменту их выполнения цикл уже завершён, а `i` равно 333. Поэтому все три вызова выводят одно и то же значение.
Ожидаемый вывод: 000, 111, 222.
Фактический вывод: 333, 333, 333.
Почему так происходит (кратко): цикл выполняется быстро, затем через 100100100 мс все три таймаута выполняют одну и ту же функцию, читающую текущее значение `i` (которое стало 333).
Несколько корректных решений (с объяснением):
1) Использовать `let` (блочная область видимости, новая привязка при каждой итерации):
```js
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
```
Выведет: 0, 1, 2.
2) Замыкание через IIFE (создать копию `i` в параметре функции):
```js
for (var i = 0; i < 3; i++) {
(function (j) {
setTimeout(() => console.log(j), 100);
})(i);
}
```
3) Передать значение как аргумент `setTimeout` (в средах, где это поддерживается):
```js
for (var i = 0; i < 3; i++) {
setTimeout(console.log, 100, i);
}
```
4) Использовать `Function.prototype.bind` чтобы зафиксировать аргумент:
```js
for (var i = 0; i < 3; i++) {
setTimeout(console.log.bind(null, i), 100);
}
```
5) Итерация по массиву/`forEach` с `let`/стрелочной функцией:
```js
[0, 1, 2].forEach(i => setTimeout(() => console.log(i), 100));
```
Выберите вариант в зависимости от поддержки среды и стиля кода (рекомендуется `let` — самый простой и современный).
12 Ноя 2025 в 10:25
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир