Доброго времени суток, программисты. Уже давно пишу на js и, естественно, в курсе сюрпризов JavaScript относительно замыкание внутри closures. Хочу понять механику того, почему JavaScript на этапе итерации теряет локальную переменную i, возвращая в итоге, допустим, при i < 10, 10-ку. Что, собственно, и показано ниже. В данном случае, на сколько я понимаю, асинхронный таймаут медленнее цикла, поэтому к моменту его исполнения таймаута i = 10.
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
Теперь несколько примеров, которые делают так, чтобы все было ок :
1) Пожалуй, самый распространённый. В данном случае анонимная функция запускается моментально, передавая в замыкание текущий i, используя обёртку.
for(var i = 0; i < 10; i++) {
(function(e) {
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
2) По-идее, то же самое.
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e);
}
})(i), 1000)
}
3) Штука, которой пользуюсь я. Написал сам, выглядит более интуитивно, особенно проще воспринимается в больших проектах на чисто ванильном js.
function count(i) {
return setTimeout(function(){
console.log(i);
}, 1000);
}
for ( var i = 0 ; i < 10 ; i++ ) {
count(i);
}
4) Еще один безумный случай, написанный мной просто для фана. Работает аналогично и быстрее остальных случаев.
setTimeout(function(){
for(var i = 0; i < 10; console.log(i++)) {}
}, 1000)
Выше перечислены не все возможные приёмы использование. Также можно сделать подобную операцию, используя call, apply, bind, передавая в функцию-обёртку значения из цикла.
Основная суть моего вопроса : как вы видите механику работы замыкания внутри цикла? Какие еще вы знаете приёмы работы с ними?