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