> Что происходит при обращении к переменной var и let до объявления в JavaScript (JavaScript)

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

Компании: РСХБ, Kaspersky

Стек: JavaScript

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

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

При обращении к переменной, объявленной через var, до её объявления мы получим undefined из-за hoisting (всплытие) и инициализации значением undefined. При обращении к let до объявления возникнет ReferenceError - переменная находится во временной мёртвой зоне (temporal dead zone, TDZ) от начала блока до строки объявления, хотя hoisting тоже происходит.

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

В JavaScript обе конструкции (var и let) подвержены hoisting - поднятию объявления переменной в начало области видимости. Однако механизмы инициализации различаются.

var поднимается и инициализируется значением undefined сразу. Поэтому к var можно обратиться до строки объявления - ошибки не будет, но значение будет undefined.

letconst) также поднимаются, но не инициализируются. Переменная находится в TDZ с начала блока (функции, цикла, условного оператора) до момента, когда выполнение дойдёт до строки с let. Любое обращение к переменной в этой зоне вызывает ReferenceError. TDZ защищает от использования переменной до её полноценного объявления.

Пример с var:

JAVASCRIPT
console.log(a); // undefined
var a = 5;

Пример с let:

JAVASCRIPT
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 10;

TDZ также распространяется на параметры функций с дефолтными значениями и на typeof - для let в TDZ typeof тоже выбросит ошибку, в отличие от var.

На практике

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

Пример кода

JAVASCRIPT
// var - hoisting с инициализацией undefined
function varExample() {
console.log(x); // undefined
var x = 1;
console.log(x); // 1
}
// let - hoisting без инициализации (TDZ)
function letExample() {
console.log(y); // ReferenceError
let y = 2;
console.log(y);
}
// TDZ в блоке
{
console.log(z); // ReferenceError
let z = 3;
}
// typeof в TDZ
{
typeof w; // ReferenceError, если w объявлена let ниже
let w = 4;
}

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

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

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

  • Понимание hoisting как механизма поднятия объявления, а не инициализации.
  • Знание TDZ и её границ (весь блок до строки объявления).
  • Умение различать поведение var и let/const в контексте области видимости и инициализации.
  • Практическое понимание, почему let предпочтительнее в современном JavaScript.

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

  • Утверждение, что let не подвержен hoisting - это неверно, hoisting есть, но без инициализации.
  • Путаница между hoisting и TDZ: hoisting - поднятие объявления, TDZ - период до инициализации.
  • Ожидание undefined для let до объявления - на самом деле будет ошибка.
  • Игнорирование TDZ для typeof - для let в TDZ typeof тоже выбрасывает ошибку, в отличие от необъявленной переменной.
  • Непонимание, что TDZ действует на весь блок, включая вложенные функции, объявленные до let.

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

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