На JavaScript показан код: for (var i=0;iconsole.log(i),100);} Объясните вывод этого кода, уникальные свойства замыканий и переменных var/let, и как переписать код, чтобы он печатал 0..4
Вывод: этот код напечатает пять раз одно и то же число — 555. Почему так происходит (коротко): - Переменная `var i` — function‑scoped и одна общая для всех итераций. После завершения цикла её значение равно 555. - Функции, переданные в `setTimeout`, создают замыкания, которые захватывают ссылку на переменную `i`, а не её текущее значение. Когда таймауты сработают (~100100100 мс позже), они читают текущее значение `i` — 555 — и выводят его пять раз. Ключевые свойства замыканий и `var`/`let`: - Замыкание хранит ссылку на внешние переменные; их жизненный цикл продлевается до момента, пока замыкание доступно. - `var`: функциональная область видимости, одно связывание на всю функцию/скрипт; в цикле все итерации видят ту же переменную. - `let`: блочная область видимости; в `for (let i = ...)` для каждой итерации создаётся новое связывание `i`, поэтому замыкание видит значение конкретной итерации. Как переписать, чтобы печатало 000–444: 1) Использовать `let` (самый простой): ```js for (let i = 0; i < 5; i++) { setTimeout(() => console.log(i), 100); } ``` Вывод: `0 1 2 3 4` (каждое в отдельной строке). 2) Создать локальную копию через IIFE (для `var`): ```js for (var i = 0; i < 5; i++) { (function(j) { setTimeout(() => console.log(j), 100); })(i); } ``` 3) Передать значение как аргумент в `setTimeout`: ```js for (var i = 0; i < 5; i++) { setTimeout((j) => console.log(j), 100, i); } ``` 4) Использовать `bind`: ```js for (var i = 0; i < 5; i++) { setTimeout(console.log.bind(null, i), 100); } ``` Выберите подходящий вариант (рекомендуется `let`).
Почему так происходит (коротко):
- Переменная `var i` — function‑scoped и одна общая для всех итераций. После завершения цикла её значение равно 555.
- Функции, переданные в `setTimeout`, создают замыкания, которые захватывают ссылку на переменную `i`, а не её текущее значение. Когда таймауты сработают (~100100100 мс позже), они читают текущее значение `i` — 555 — и выводят его пять раз.
Ключевые свойства замыканий и `var`/`let`:
- Замыкание хранит ссылку на внешние переменные; их жизненный цикл продлевается до момента, пока замыкание доступно.
- `var`: функциональная область видимости, одно связывание на всю функцию/скрипт; в цикле все итерации видят ту же переменную.
- `let`: блочная область видимости; в `for (let i = ...)` для каждой итерации создаётся новое связывание `i`, поэтому замыкание видит значение конкретной итерации.
Как переписать, чтобы печатало 000–444:
1) Использовать `let` (самый простой):
```js
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100);
}
```
Вывод: `0 1 2 3 4` (каждое в отдельной строке).
2) Создать локальную копию через IIFE (для `var`):
```js
for (var i = 0; i < 5; i++) {
(function(j) {
setTimeout(() => console.log(j), 100);
})(i);
}
```
3) Передать значение как аргумент в `setTimeout`:
```js
for (var i = 0; i < 5; i++) {
setTimeout((j) => console.log(j), 100, i);
}
```
4) Использовать `bind`:
```js
for (var i = 0; i < 5; i++) {
setTimeout(console.log.bind(null, i), 100);
}
```
Выберите подходящий вариант (рекомендуется `let`).