Приведён фрагмент на JavaScript: for (var i = 0; i console.log(i), 0); } объясните поведение вывода и предложите как минимум два способа изменить код, чтобы он печатал 0,1,2
Коротко: из‑за `var` переменная `i` общая для всех замыканий; цикл успевает завершиться и `i` становится равным 333, затем все таймауты выполняются и печатают это же значение — фактически вывод будет 3, 3, 33,\,3,\,33,3,3. Хотим получить 0,1,20,1,20,1,2. Ниже — несколько способов. 1) Использовать `let` в заголовке цикла (блочная область для каждой итерации): ``` for (let i = 0; i < 3; i++) { setTimeout(() => console.log(i), 0); } ``` Выведет: 0, 1, 2. 2) Захватить текущее значение в замыкании через IIFE: ``` for (var i = 0; i < 3; i++) { (function(j) { setTimeout(() => console.log(j), 0); })(i); } ``` Тут в каждую итерацию создаётся своя `j`, вывод будет 0, 1, 2. 3) Передать значение как аргумент `setTimeout` или использовать `bind`: ``` for (var i = 0; i < 3; i++) { setTimeout(function(j) { console.log(j); }, 0, i); // или // setTimeout(console.log.bind(null, i), 0); } ``` Обе версии тоже печатают 0, 1, 2. Выбирайте `let` как самое простое и современное решение; IIFE и передача аргумента полезны при необходимости поддержать старый код.
1) Использовать `let` в заголовке цикла (блочная область для каждой итерации):
```
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0);
}
```
Выведет: 0, 1, 2.
2) Захватить текущее значение в замыкании через IIFE:
```
for (var i = 0; i < 3; i++) {
(function(j) {
setTimeout(() => console.log(j), 0);
})(i);
}
```
Тут в каждую итерацию создаётся своя `j`, вывод будет 0, 1, 2.
3) Передать значение как аргумент `setTimeout` или использовать `bind`:
```
for (var i = 0; i < 3; i++) {
setTimeout(function(j) { console.log(j); }, 0, i);
// или
// setTimeout(console.log.bind(null, i), 0);
}
```
Обе версии тоже печатают 0, 1, 2.
Выбирайте `let` как самое простое и современное решение; IIFE и передача аргумента полезны при необходимости поддержать старый код.