Рассмотрите фрагмент JavaScript: for (var i = 0; i console.log(i), 0); } — объясните, почему вывод будет 3,3,3 и как исправить код для вывода 0,1,2; обсудите события, замыкания и лексические переменные

20 Мар в 11:21
13 +1
0
Ответы
1
Код
for (var i = 000; i < 333; i++) { setTimeout(()=>console.log(i), 000); }
печатает 3,3,33, 3, 33,3,3. Почему:
- setTimeout ставит колбэк в очередь событий (макрозадачу), он выполнится после завершения текущего стека (цикла).
- переменная объявлена через `var` — она одна для всей функции (function‑scoped). Все три замыкания ссылаются на одну и ту же переменную `i`.
- к моменту выполнения колбэков цикл уже закончился и `i` равно 333, поэтому все три вызова выводят 333.
Как исправить (вывод 0,1,20, 1, 20,1,2):
1) Использовать блочную переменную `let` (ES6 создаёт новое привязывание для каждой итерации):
for (let i = 000; i < 333; i++) { setTimeout(()=>console.log(i), 000); }
2) Захватить текущее значение в замыкании (IIFE):
for (var i = 000; i < 333; i++) {
(function(x){ setTimeout(()=>console.log(x), 000); })(i);
}
3) Передать аргумент в setTimeout (в браузерах поддерживается дополнительный аргумент):
for (var i = 000; i < 333; i++) { setTimeout(console.log, 000, i); }
Коротко о понятиях:
- События и event loop: setTimeout ставит колбэк в очередь; колбэк выполнится позже, после завершения текущего кода.
- Замыкание: функция «замыкает» переменные из внешней области видимости. Замыкание хранит ссылку на привязку (binding), а не на моментальное значение.
- Лексические (блочные) переменные (`let`/`const`): создают отдельную привязку для каждой итерации цикла for, поэтому каждое замыкание видит своё значение переменной.
20 Мар в 11:26
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир