Почему var всплывает и что происходит при всплытии в JavaScript
Что проверяют
Знаете ли вы, что объявления обрабатываются до выполнения кода, и объясните ли разницу между var и let через момент инициализации, а не заклинанием «let не всплывает». Это базовый вопрос, по нему быстро отделяют заучивших от понимающих.
Как отвечать
Перед выполнением кода движок создаёт лексическое окружение и регистрирует в нём все объявления области. Для var привязка создаётся сразу и тут же инициализируется значением undefined, а присваивание остаётся на своём месте.
console.log(x); // undefined
var x = 5;
console.log(x); // 5Движок видит это примерно так:
var x;
console.log(x);
x = 5;Детали, которые отличают знающего:
- область видимости у
varфункциональная, блок её не ограничивает, а на верхнем уровне классического скрипта объявление создаёт свойство глобального объекта; letиconstтоже поднимаются, но остаются неинициализированными, и обращение до объявления даётReferenceError. Этот отрезок называют временной мёртвой зоной;- объявление функции поднимается вместе с телом, поэтому вызвать её можно выше по коду. Функциональное выражение в
varдо присваивания равноundefined, а вызов даётTypeError; - повторный
varс тем же именем допустим и не сбрасывает значение, повторныйletэто синтаксическая ошибка.
Где спотыкаются
Говорят, что код физически переносится наверх. Ничего никуда не двигается, просто создание привязки и присваивание значения разнесены по времени, и первое происходит до выполнения строки.
Утверждают, что let не всплывает. Всплывает точно так же, отличается только то, что привязка не получает начального значения, и любое обращение к ней до объявления падает, а не возвращает undefined.
Попадаются на цикле с var и колбэками: переменная одна на весь цикл, поэтому все отложенные вызовы видят её последнее значение. let создаёт отдельную привязку на каждой итерации, и это самая частая причина перехода на него.