На примере JavaScript-кода: for (var i=0;iconsole.log(i),100); } Почему выводит 3,3,3 и как исправить? Обсудите связанные с этим концепции замыканий и области видимости

17 Ноя в 06:52
2 +1
0
Ответы
1
Код
```
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
```
выводит 3,3,33, 3, 33,3,3. Почему:
- `var` — функционно (не блочно) область видимости: в этом примере существует одна переменная `i`, общая для всех итераций.
- `setTimeout` планирует колбэки асинхронно; к моменту их выполнения цикл уже завершится и `i` станет 333.
- Замыкание в колбэке захватывает ссылку на переменную `i`, а не её значение в момент создания колбэка, поэтому все колбэки увидят текущее значение 333.
Как исправить (варианты):
1) Использовать `let` (блочная область — для каждой итерации своя привязка):
```
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
}
```
Выведет 0,1,20, 1, 20,1,2.
2) Создать замыкание с явным захватом значения (IIFE):
```
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 100);
})(i);
}
```
3) Передать значение в `setTimeout` (в средах, где поддерживается):
```
for (var i = 0; i < 3; i++) {
setTimeout(console.log, 100, i);
}
```
или
```
for (var i = 0; i < 3; i++) {
setTimeout((j) => console.log(j), 100, i);
}
```
Коротко про концепции:
- Замыкание — функция «запоминает» доступ к переменным внешней области, но это ссылка на переменную, а не её снимок.
- Блочная область (`let`, `const`) даёт новую привязку переменной для каждой итерации цикла, что решает проблему без дополнительных замыканий.
17 Ноя в 06:58
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир