Циклы и замыкания

Читаю книгу "You don't know JavaScript". Тема - замыкания.

for (var i=1; i<=5; i++) {
	setTimeout( function timer(){
		console.log( i );
	}, i*1000 );
}

Код выше, по словам автора, выведет 6 раз шестерку, ибо

Все функции обратного вызова функции timeout запускаются прямо после завершения цикла

Проблема была решена следующим образом:

for (var i=1; i<=5; i++) {
	(function(j){
		setTimeout( function timer(){
			console.log( j );
		}, j*1000 );
	})( i );
}

Аргумент анонимной функции j перенял ссылку на глобальное i. Это ок. Но вот следующее меня очень смущает:

for (let i=1; i<=5; i++) {
	setTimeout( function timer(){
		console.log( i );
	}, i*1000 );
}

Осознаю разницу между let и var. С let переменная i видима только для своего блока. В данном случае для цикла. В то время, как var глобален. С ним можно получить i вне блока. Но почему в последнем примере setTimeout не сработал после цикла, как было озвучено выше. Ведь вся разница с самым первым примером кода и последним в доступе i вне блока for. Я думал, что замыканием внутри анонимной функции и решается проблема запуска setTimeout после цикла, а не во время него. Так почему при условии глобального i setTimeout запустился после цикла, а при локальной i setTimeout запускается при каждой итерации цикла?


Ответы (1 шт):

Автор решения: Pavel Grishaev

setTimeout в любом случае асинхронный и всегда запустится позже цикла. Разница в том, что с let эта переменная не одна, а создается другая новая на каждый шаг цикла, и функция в таймауте каждый раз обращается к разным переменным, а не к одной изменяемой.

Цитата из https://learn.javascript.ru/let-const:

При использовании в цикле, для каждой итерации создаётся своя переменная.

Переменная var – одна на все итерации цикла и видна даже после цикла:

for(var i=0; i<10; i++) { /* … */ }

alert(i); // 10 С переменной let – всё по-другому.

Каждому повторению цикла соответствует своя независимая переменная let. Если внутри цикла есть вложенные объявления функций, то в замыкании каждой будет та переменная, которая была при соответствующей итерации.

→ Ссылка