На JavaScript следующий код: for (var i = 0; i console.log(i), 0); } — почему печатает 3 три раза, как это связано с замыканиями и областями видимости, и какие способы исправления вы предложите

29 Янв в 11:23
18 +1
0
Ответы
1
Коротко: потому что стрелочная функция в setTimeout замыкает переменную iii (не её текущее значение), а переменная объявлена через `var` — она одна для всей функции. Цикл выполняется синхронно и к моменту выполнения асинхронных колбэков значение iii уже равно 333, поэтому выводится 333 три раза.
Почему так происходит (по шагам):
- `var i = 0` создаёт одну функцию‑уровневую переменную `i`.
- Внутри цикла мы создаём три колбэка, каждый замыкает ссылку на ту же самую переменную `i`.
- setTimeout запускает колбэки асинхронно (после завершения текущего стека). К моменту их вызова цикл уже завершён и `i === 333`.
Способы исправить (короткие примеры):
1) Использовать `let` в заголовке цикла (новая привязка на каждую итерацию):
```js
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
// Выведет: 0 1 2
```
2) Замыкание через IIFE (захватить значение в параметр):
```js
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 0);
})(i);
}
// Выведет: 0 1 2
```
3) Передать аргумент в setTimeout (поддерживается в браузерах и Node):
```js
for (var i = 0; i < 3; i++) {
setTimeout(function(j) { console.log(j); }, 0, i);
}
// Выведет: 0 1 2
```
4) Использовать bind, чтобы зафиксировать значение:
```js
for (var i = 0; i < 3; i++) {
setTimeout(console.log.bind(null, i), 0);
}
// Выведет: 0 1 2
```
5) Использовать методы массива / функциональный стиль:
```js
[0,1,2].forEach(i => setTimeout(() => console.log(i), 0));
```
Вывод: проблема — ссылка в замыкании + `var` (функциональная область видимости) и асинхронность; решать — создать отдельную привязку значения для каждой итерации (через `let`, IIFE, bind, аргументы setTimeout и т.д.).
29 Янв в 11:30
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир