Как создаются переменные в JavaScript?
Что проверяют
Не синтаксис, а понимание разницы между var, let и const: область видимости, подъём, временная мёртвая зона. Следом почти всегда показывают цикл с setTimeout или спрашивают, можно ли изменить объект, объявленный через const.
Как отвечать
var: область видимости функции, а не блока. Объявление поднимается и сразу инициализируетсяundefined, поэтому обращение до строки объявления не падает. Можно объявить повторно в той же области. На верхнем уровне обычного скрипта создаёт свойствоwindow;let: блочная область, повторное объявление в той же области запрещено, переприсваивание разрешено;const: блочная область, инициализация обязательна, переприсвоить нельзя.
Про подъём скажите точно: let и const тоже поднимаются, но до строки объявления находятся во временной мёртвой зоне (TDZ), и обращение даёт ReferenceError. Даже typeof x в TDZ бросает ошибку, хотя для необъявленной переменной вернул бы "undefined".
Практическое правило: по умолчанию const, let там, где значение правда меняется, а var в новом коде не нужен. Присваивание без объявления в нестрогом режиме создаёт глобальную переменную, а в ES-модулях, которые всегда работают в строгом режиме, даёт ReferenceError.
Где спотыкаются
Говорят, что const делает значение неизменяемым. Он запрещает только переприсваивание: объект из const user = {} можно дополнять свойствами, в массив можно делать push. Заморозить объект помогает Object.freeze, и то только на один уровень.
Не могут объяснить цикл for (var i = 0; i < 3; i++) setTimeout(() => console.log(i)). Он выведет три раза 3: var одна на весь цикл, а колбэки выполнятся после его окончания. С let на каждой итерации создаётся новая привязка, и выводится 0, 1, 2.
Путают var на верхнем уровне скрипта и модуля. В модуле переменная остаётся локальной и в window не попадает, поэтому старый код, который рассчитывал на глобальную var, после перехода на сборщик ломается.