Почему let и const выдают ошибку при обращении до объявления в JavaScript
Что проверяют
Знаете ли вы, что происходит при входе в область видимости, и не повторяете ли ходовую неточность «let и const не поднимаются». Правильная модель другая: привязка создаётся заранее, но остаётся неинициализированной, и чтение до объявления запрещено спецификацией.
Как отвечать
При входе в блок или функцию движок заводит привязки для всех объявлений сразу. Для var привязка тут же получает undefined, для let, const и class она помечается как неинициализированная. Отрезок от начала области видимости до строки объявления называют временной мёртвой зоной: любое чтение там бросает ReferenceError: Cannot access 'x' before initialization.
Текст ошибки стоит назвать отдельно, он отличается от x is not defined для необъявленной переменной. Это удобный способ показать, что вы различаете «объявлена, но недоступна» и «не объявлена вовсе».
Зачем так сделали: у const нет осмысленного значения до присваивания, а тихий undefined у var прячет ошибку порядка вместо того, чтобы её показать.
{
typeof x; // ReferenceError, хотя для необъявленного typeof безопасен
let x = 1;
}
let y = y; // тоже ошибка: правая часть читается ещё в мёртвой зонеГраница зоны определяется позицией в коде, а не временем: функция, объявленная выше и вызванная после строки объявления, прочитает переменную нормально.
Где спотыкаются
Говорят, что let и const не поднимаются. Поднимаются, вся разница в инициализации, и грамотный интервьюер копает ровно сюда.
Считают typeof безопасной проверкой во всех случаях. Для необъявленного идентификатора он вернёт строку, а в мёртвой зоне бросит исключение, и старый приём с проверкой через typeof перестаёт работать.
Смешивают три разные темы: мёртвую зону, блочную область видимости и неизменяемость. const запрещает переприсваивание привязки, но не запрещает менять поля объекта, а к порядку объявлений это вообще отношения не имеет.