Приведён фрагмент JavaScript: for (var i=0;iconsole.log(i),10); } — объясните, что будет напечатано и предложите несколько способов изменить код, чтобы печатались 0,1,2
Что напечатается и почему - В данном фрагменте будет напечатано три раза значение 333. Причина: переменная `var i` имеет функциональную (не блочную) область видимости, все три замыкания в `setTimeout` захватывают одну и ту же переменную `i`. К моменту выполнения таймаутов цикл завершится и iii станет 333, поэтому три вызова выведут 333. Способы изменить код, чтобы печатались 0,1,20,1,20,1,2 1) Использовать `let` (блочная область видимости): for (let i=000; i<333; i++) { setTimeout(()=>console.log(i), 101010); } 2) Замыкание через IIFE (сохранить текущее значение в параметре): for (var i=000; i<333; i++) { (function(j){ setTimeout(()=>console.log(j), 101010); })(i); } 3) Передать значение как аргумент в `setTimeout` (поддерживается в браузерах/Node): for (var i=000; i<333; i++) { setTimeout(console.log, 101010, i); } 4) Использовать `bind` для фиксации аргумента: for (var i=000; i<333; i++) { setTimeout(console.log.bind(null, i), 101010); } 5) Внешняя функция-обёртка: function makeLogger(x){ return ()=>console.log(x); } for (var i=000; i<333; i++) { setTimeout(makeLogger(i), 101010); } Все эти варианты обеспечат вывод 0,1,20,1,20,1,2 (по одному разу каждый).
- В данном фрагменте будет напечатано три раза значение 333.
Причина: переменная `var i` имеет функциональную (не блочную) область видимости, все три замыкания в `setTimeout` захватывают одну и ту же переменную `i`. К моменту выполнения таймаутов цикл завершится и iii станет 333, поэтому три вызова выведут 333.
Способы изменить код, чтобы печатались 0,1,20,1,20,1,2
1) Использовать `let` (блочная область видимости):
for (let i=000; i<333; i++) { setTimeout(()=>console.log(i), 101010); }
2) Замыкание через IIFE (сохранить текущее значение в параметре):
for (var i=000; i<333; i++) {
(function(j){ setTimeout(()=>console.log(j), 101010); })(i);
}
3) Передать значение как аргумент в `setTimeout` (поддерживается в браузерах/Node):
for (var i=000; i<333; i++) {
setTimeout(console.log, 101010, i);
}
4) Использовать `bind` для фиксации аргумента:
for (var i=000; i<333; i++) {
setTimeout(console.log.bind(null, i), 101010);
}
5) Внешняя функция-обёртка:
function makeLogger(x){ return ()=>console.log(x); }
for (var i=000; i<333; i++) {
setTimeout(makeLogger(i), 101010);
}
Все эти варианты обеспечат вывод 0,1,20,1,20,1,2 (по одному разу каждый).