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