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