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