Объясните поведение и результат этого JavaScript‑фрагмента, укажите, почему так происходит, и предложите как минимум два способа исправить его, чтобы получить ожидаемый вывод 0,1,2 (один способ с ES5 и один с ES6+):
for (var i = 0; i console.log(i), 10); }

29 Окт в 09:22
3 +3
0
Ответы
1
Коротко: фрагмент выведет три раза 333 (т.е. 3, 3, 3\,3,\;3,\;33,3,3), потому что все колбэки замыкают одну переменную iii, а таймауты выполняются после завершения цикла, когда iii стало 333. Ожидаемый вывод — 0, 1, 2\,0,\,1,\,20,1,2.
Почему так происходит:
- `var` имеет функциональную (не блочную) область видимости, поэтому в каждой итерации используется одна и та же переменная `i`.
- стрелочные функции/функции внутри `setTimeout` замыкают ссылку на эту переменную, а не её значение в момент создания.
- когда таймауты срабатывают (через 10\,1010 мс), цикл уже завершён и `i === 3`.
Способы исправить.
ES5 (IIFE — замыкание на копии значения):
for (var i = 0; i < 3; i++) {
(function(iCopy) {
setTimeout(function() { console.log(iCopy); }, 10);
})(i);
}
ES6+ (блочная переменная `let`, новая привязка на каждую итерацию):
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 10);
}
Доп. альтернативы:
- Передать значение как аргумент `setTimeout` (поддерживается в средах Node/браузерах):
for (var i = 0; i < 3; i++) {
setTimeout(function(x) { console.log(x); }, 10, i);
}
- Использовать `bind`:
for (var i = 0; i < 3; i++) {
setTimeout(console.log.bind(null, i), 10);
}
Все приведённые исправления дадут ожидаемый вывод 0, 1, 2\,0,\,1,\,20,1,2.
29 Окт в 09:54
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир