> Почему в JavaScript переменная, объявленная через var, всплывает и инициализируется значением undefined? (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Альфа-банк

Стек: JavaScript

> Пример ответа

Короткий ответ

Это поведение - следствие двух механизмов: hoisting и фазы создания переменной в execution context. При подъёме var объявление перемещается в начало области видимости, но инициализация остаётся на месте. На этапе создания контекста движок выделяет память под переменную и автоматически присваивает ей undefined - это значение по умолчанию для неинициализированных переменных. Поэтому до строки с присваиванием переменная доступна, но содержит undefined, а не вызывает ReferenceError, как let или const.

Подробное объяснение

JavaScript обрабатывает код в два прохода. На первом проходе (compile phase) парсер находит все объявления var и function в текущей области видимости и "поднимает" их в начало. Это называется hoisting. Однако поднимается только объявление (var x), а не присваивание (x = 10).

На втором проходе (execution phase) создаётся execution context. Для каждого контекста (глобального или функционального) движок создаёт environment record - структуру, хранящую привязки имён. При создании записи для var-переменной движок:

  1. Выделяет слот в памяти.
  2. Инициализирует его значением undefined.
  3. Помечает привязку как доступную для чтения и записи.

Это происходит до выполнения любого кода в контексте. Поэтому когда выполнение доходит до строки console.log(x), переменная уже существует в environment record со значением undefined.

Для let и const механизм иной: они тоже hoist, но остаются в temporal dead zone (TDZ) - до строки объявления обращение к ним вызывает ReferenceError. Это осознанное дизайн-решение: var унаследован от ранних версий языка, где не было блочной области видимости и TDZ, а undefined как значение по умолчанию был простейшим способом сигнализировать "ещё не присвоено".

На практике

На практике это поведение создаёт ловушки:

  • Переменная видна до объявления, что противоречит интуиции и может маскировать ошибки.
  • В циклах var не создаёт новую область видимости на каждой итерации - все итерации используют одну переменную.
  • В функциях var всплывает в начало функции, а не блока, поэтому if или for не ограничивают её видимость.

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

Пример кода

JAVASCRIPT
console.log(x); // undefined - не ReferenceError
var x = 10;
// Эквивалентно:
var x;
console.log(x); // undefined
x = 10;
// Ловушка с var в цикле:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i)); // 3, 3, 3
}
// С let - ожидаемо:
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j)); // 0, 1, 2
}

Как отвечать на собеседовании

Начните с краткого определения hoisting, затем объясните двухфазный процесс создания execution context. Подчеркните разницу между объявлением и инициализацией. Упомяните, что undefined - это значение по умолчанию, которое движок присваивает на этапе создания привязки. Затем сравните с let/const и TDZ. Если спросят про function - отметьте, что функции поднимаются целиком, включая тело, поэтому их можно вызывать до объявления.

Что проверяет интервьюер

Интервьюер оценивает:

  • Понимание разницы между объявлением и инициализацией.
  • Знание этапов создания execution context.
  • Умение объяснить, почему именно undefined, а не ошибка.
  • Осознание практических последствий для кода.
  • Способность сравнить с современными let/const.

Типичные ошибки

  • Утверждение, что "переменная поднимается со значением undefined" - на самом деле поднимается только объявление, а undefined присваивается при создании контекста.
  • Смешение hoisting для var и function - функции поднимаются целиком, переменные - только объявление.
  • Игнорирование TDZ для let/const - кандидат может сказать, что они "не всплывают", хотя они всплывают, но недоступны.
  • Непонимание, что undefined - это не "отсутствие значения", а конкретное значение типа undefined.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью