24 Ноя в 09:23
1 +1
0
Ответы
1
Коротко — потому что в исходном фрагменте переменная `i` объявлена через `var` (функциональная область видимости), все три функции в `setTimeout` захватывают одну и ту же переменную `i`. Цикл завершается до выполнения таймаутов, `i` становится равной ......... (то есть .........), поэтому каждая функция выводит это значение, а не свои ожидаемые ........., ........., ..........
Механизмы, дающие такое поведение:
- Замыкание: функция захватывает ссылку на переменную, а не её текущее значение.
- Область видимости `var`: одна переменная `i` для всех итераций.
- Event loop / макрозадачи: колбэки `setTimeout` выполняются асинхронно после завершения синхронного цикла.
Как исправить, сохранив логику (несколько простых вариантов):
1) Использовать `let` в заголовке цикла (блоковая область видимости — для каждой итерации своя `i`):
```js
for (let i = 0; i < 3; i++) {
setTimeout(function() { console.log(i); }, 10);
}
```
Ожидаемый вывод: `0`, `1`, `2`.
2) Закрыть текущее значение в IIFE (поддерживает старые окружения без `let`):
```js
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(function() { console.log(j); }, 10);
})(i);
}
```
3) Передать аргументы в `setTimeout` (в современных средах поддерживается):
```js
for (var i = 0; i < 3; i++) {
setTimeout(function(j) { console.log(j); }, 10, i);
}
```
4) Создать фабрику функций:
```js
function makeLogger(x) {
return function() { console.log(x); };
}
for (var i = 0; i < 3; i++) {
setTimeout(makeLogger(i), 10);
}
```
Любой из этих подходов сохраняет асинхронную логику, но гарантирует, что каждая функция получит своё значение итерации (........., ........., .........).
24 Ноя в 09:31
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир