Приведён кусок JavaScript: setTimeout(()=>console.log(i),1000) в цикле for (var i=0;i

1 Июн в 14:49
8 +1
0
Ответы
1
Проблема и почему так выводится
- В коде с `for (var i = 0; i console.log(i), 1000)` переменная `i` объявлена через `var`, она имеет функциональную (не блочную) область видимости. Колбэки, переданные в `setTimeout`, выполнятся примерно через 100010001000 мс, после того как цикл завершится, и все они читают одну и ту же переменную `i`, значение которой к тому моменту равно 555. Поэтому вывод будет пять раз 555.
Способы исправить (чтобы вывести 0…40\ldots404)
1) Использовать `let` в заголовке цикла (блочная область для каждой итерации):
```
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 1000);
}
```
Объяснение: для каждой итерации создаётся своё `i`.
2) Захват значения через IIFE (немедленно вызываемая функция):
```
for (var i = 0; i < 5; i++) {
(function (j) {
setTimeout(() => console.log(j), 1000);
})(i);
}
```
Объяснение: `j` — параметр новой функции, фиксирует текущее значение `i` (копируется по значению).
3) Передать аргумент в `setTimeout` (поддерживается в браузерах/Node):
```
for (var i = 0; i < 5; i++) {
setTimeout((j) => console.log(j), 1000, i);
}
```
Объяснение: `setTimeout` сам вызовет функцию с переданным аргументом `i`.
4) Создать локальную переменную `let` внутри тела цикла:
```
for (var i = 0; i < 5; i++) {
let j = i;
setTimeout(() => console.log(j), 1000);
}
```
5) Использовать `Function.prototype.bind` для привязки аргумента:
```
for (var i = 0; i < 5; i++) {
setTimeout(console.log.bind(null, i), 1000);
}
```
Объяснение: `bind` создаёт функцию с уже зафиксированным значением аргумента.
Разница между `var`, `let` и замыканиями (кратко)
- `var`: функциональная область видимости или глобальная; одна и та же переменная доступна во всех итерациях цикла. При создании замыканий они захватывают ссылку на эту переменную, поэтому все функции увидят её финальное значение.
- `let`: блочная область видимости; в заголовке `for` для каждой итерации создаётся отдельная привязка переменной, из-за чего замыкания видят своё собственное значение.
- Замыкания: функции «замыкают» переменные окружения (ссылку на переменную). Если нужно зафиксировать текущее значение, его надо скопировать в новую область (через параметр функции, `let`-переменную и т.п.).
1 Июн в 15:33
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир