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

12 Мая в 07:55
24 +1
0
Ответы
1
Коротко — почему так происходит:
- В исходном коде переменная объявлена как `var i`, то есть имеет функциональную (не блочную) область видимости. Цикл выполняется быстро и завершает работу, после чего `i` становится равным 333 (последнее значение, при котором условие i<3i<3i<3 перестало выполняться).
- `setTimeout(..., 0)` ставит колбэки в очередь событий; они выполнятся только после завершения текущего стека вызовов, то есть когда цикл уже закончился. Все три замыкания ссылаются на одну и ту же переменную `i`, поэтому каждый колбэк выведет текущее значение i=3i=3i=3. Результат: три строки с одним и тем же числом (3).
Как исправить (несколько приёмов):
1) Использовать `let` в заголовке цикла (ES6) — блочная привязка для каждой итерации
```javascript
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
```
Выведет 0,1,20,1,20,1,2.
2) Создать локальную копию через `let` внутри цикла
```javascript
for (var i = 0; i < 3; i++) {
let j = i;
setTimeout(() => console.log(j), 0);
}
```
3) Использовать IIFE (немедленно-выполняемое функциональное выражение) — классический приём до ES6
```javascript
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 0);
})(i);
}
```
4) Передать аргумент в `setTimeout` (передаёт параметры в колбэк)
```javascript
for (var i = 0; i < 3; i++) {
setTimeout((x) => console.log(x), 0, i);
}
```
5) Использовать `Function.prototype.bind` для фиксирования аргумента
```javascript
for (var i = 0; i < 3; i++) {
setTimeout(console.log.bind(null, i), 0);
}
```
6) Использовать современный `for...of` или `Array.prototype.forEach` (вместо `var`)
```javascript
[0,1,2].forEach(i => setTimeout(() => console.log(i), 0));
```
Всё сводится к одной идее: дать каждому колбэку свою копию индекса (блочная переменная или захват аргумента), чтобы замыкание не ссылалось на общую изменяемую `var i`.
12 Мая в 08:00
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Гарантированные бесплатные доработки в течение 1 года
Быстрое выполнение от 2 часов
Проверка работы на плагиат
Поможем написать учебную работу
Прямой эфир