Задать вопрос
@zwoc

Область видимости у var и let внутри цикла. Как правильно?

Господа, здравствуйте,

проходил сегодня собеседование, и не могу пока на него найти точный ответ, почему происходит такая проблема. Суть задачи в чем: есть три ноды, надо на них повесить клик-обработчик, который бы выводил индекс в цикле.

Вот неправильно рабочий код:
var docs = ['div1', 'div2', 'div3']

for (var i = 1; i < docs.length; i++) {
document.getElementById(docs[i]).onclick = function() {
  	alert(i)
  }
}


Этот код, как вы поняли, работает, но при клике будет выводиться неверный индекс i
Объясните, пожалуйста, почему, если мы будем вместо var использовать let для переменной индекса, происходит такой коллапс?
  • Вопрос задан
  • 2055 просмотров
Подписаться 2 Средний Комментировать
Решения вопроса 2
FreeMan94
@FreeMan94
Frontend developer
Когда происходит клик, то i берется из внешнего LexicalEnvironment.
К моменту клика цикл завершился, последнее значение было i=2.
В результате значение всегда равно 2.
С переменной let не так.
Каждому повторению цикла соответствует своя независимая переменная let. Если внутри цикла есть вложенные объявления функций, то в замыкании каждой будет та переменная, которая была при соответствующей итерации.

Подробнее
Ответ написан
freislot
@freislot
Frontend-разработчик
Объявление счетчика цикла i с применением let вместо var изолирует область видимости i. Т.е значение i ограничивается областью видимости итерации цикла

Для прочтения
Переменные: let и const
Лексическая область видимости

Каждому повторению цикла соответствует своя независимая переменная let. Если внутри цикла есть вложенные объявления функций, то в замыкании каждой будет та переменная, которая была при соответствующей итерации.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
@vitstr
Front-end developer
По всей видимости, потому что если мы используем let, то на каждую итерацию цикла создается отдельный скоуп. По идее, должно работать с var если все это дело обернуть в анонимную функцию, и запустить ее с передачей текущего i в качестве аргумента.
Ответ написан
Комментировать
@Jumandjilos
Если с var, то нужно создать анонимную функцию, которая будет брать значение из замыкания, а вот let, как во многих других ЯП, при каждом проходе цикле создаёт свою переменную i, поэтому все корректно выводится
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы