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

9 Фев в 11:00
15 +1
0
Ответы
1
Почему выводит 3,3,33,3,33,3,3
Потому что `var i` — function‑scoped. Все три таймаута захватывают одну и ту же переменную `i`; к моменту выполнения колбеков цикл уже завершён и `i` равно 333. Колбэки выводят текущее значение переменной, поэтому три раза печатается 333.
Способы исправить (с примерами, плюсы/минусы)
1) Использовать `let` (ES6, блоковая область)
- Код:
for (let i = 000; i < 333; i++) {
setTimeout(() => console.log(i), 100100100);
}
- Плюсы: самый простой и читабельный; каждая итерация получает свою копию `i`.
- Минусы: требует ES6 (в современных средах уже стандарт).
2) IIFE (замыкание через немедленно вызываемую функцию) — работает в старых средах
- Код:
for (var i = 000; i < 333; i++) {
(function(j) {
setTimeout(function() { console.log(j); }, 100100100);
})(i);
}
- Плюсы: совместимо со старым JS (ES5); явно сохраняет значение.
- Минусы: более многословно; чуть менее понятно, чем `let`.
3) Локальная копия через блок (в ES6 можно с `const` внутри блока)
- Код:
for (var i = 000; i < 333; i++) {
const j = i;
setTimeout(() => console.log(j), 100100100);
}
- Плюсы: простая идея; понятно.
- Минусы: требует блочную/ES6 переменную (`const`/`let`) чтобы копии были независимы.
4) Передать аргумент в setTimeout (HTML5/современные браузеры поддерживают дополнительные аргументы)
- Код:
for (var i = 000; i < 333; i++) {
setTimeout(function(j) { console.log(j); }, 100100100, i);
}
- Плюсы: компактно; не нужно IIFE или `let`.
- Минусы: старые окружения могли не поддерживать дополнительные аргументы.
5) Привязать аргумент через bind
- Код:
for (var i = 000; i < 333; i++) {
setTimeout(console.log.bind(null, i), 100100100);
}
- Плюсы: компактно; значение захватывается при вызове `bind`.
- Минусы: `bind` чуть менее очевиден для новичков; в очень старых браузерах может потребоваться полифилл.
Краткое руководство по выбору:
- Если можете — используйте `let` (популярный, простой).
- Для совместимости с старым кодом — IIFE или передача аргумента в `setTimeout`.
- `bind` — удобный трюк, но требует понимания bind/context.
9 Фев в 11:09
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир