Что такое hoisting в JavaScript?
Что такое hoisting
Hoisting (поднятие) — это поведение движка JavaScript, при котором объявления (declarations) переменных, функций и классов обрабатываются до выполнения кода. Технически никакого физического «перемещения» строк не происходит: на этапе создания контекста выполнения движок проходит по коду и резервирует место в памяти для всех объявлений, а затем уже исполняет код построчно.
Именно поэтому к функции, объявленной через function, можно обратиться до её определения в исходном коде, а обращение к var-переменной до её объявления вернёт undefined, а не ошибку.
Как поднимаются разные сущности
var
Переменные, объявленные через var, поднимаются и инициализируются значением undefined. Поэтому обращение до объявления не выбрасывает ошибку.
console.log(x); // undefined
var x = 5;
console.log(x); // 5
Движок интерпретирует это примерно так:
var x; // объявление поднято и инициализировано как undefined
console.log(x);
x = 5;
console.log(x);
let и const
Объявления let и const также поднимаются, но не инициализируются. Переменная попадает во «временную мёртвую зону» (Temporal Dead Zone, TDZ) — от начала блока до строки объявления. Обращение к ней в этот момент вызывает ReferenceError.
console.log(y); // ReferenceError: Cannot access 'y' before initialization
let y = 10;
Function Declaration
Функциональные объявления поднимаются вместе с телом, поэтому их можно вызывать выше по коду.
greet(); // "Привет"
function greet() {
console.log("Привет");
}
Function Expression и стрелочные функции
Функции, присвоенные переменной, подчиняются правилам этой переменной (var, let, const).
sayHi(); // TypeError: sayHi is not a function
var sayHi = function () {
console.log("Hi");
};
Здесь поднимается только объявление var sayHi, а присвоение функции остаётся на своём месте.
class
Классы тоже поднимаются, но, как let/const, находятся в TDZ до момента объявления.
new User(); // ReferenceError
class User {}
Области видимости и hoisting
Важно понимать, что var имеет функциональную область видимости, а let и const — блочную. Поэтому поднятие var происходит до начала функции, а let/const — до начала ближайшего блока { ... }.
function demo() {
console.log(a); // undefined
if (true) {
var a = 1;
let b = 2;
}
console.log(a); // 1
// console.log(b); // ReferenceError
}
Зачем это знать на практике
Понимание hoisting помогает избегать неочевидных багов: обращений к переменной до её инициализации, конфликтов имён, неожиданного undefined вместо ожидаемого значения. Современный стиль — использовать let и const, объявлять переменные как можно ближе к месту использования и не полагаться на поднятие var.
Что хочет услышать интервьюер
Чёткое определение hoisting и понимание, что поднимаются объявления, а не инициализации
Знание различий в поведении var, let, const, function declaration и class
Понимание Temporal Dead Zone и того, что let/const тоже поднимаются
Различие между function declaration и function expression при поднятии
Связь hoisting с областями видимости (функциональная для var, блочная для let/const)
Пример: Поднятие var и function declaration
// Обращение к функции до её объявления работает
sayHello();
function sayHello() {
console.log("Привет, мир");
}
// var поднимается и инициализируется как undefined
console.log(count); // undefined
var count = 10;
console.log(count); // 10
Пример: Temporal Dead Zone у let и const
// Попытка обратиться к let до объявления вызовет ошибку
try {
console.log(value); // ReferenceError
let value = 42;
} catch (e) {
console.log(e.message);
}
// const ведёт себя так же
{
// здесь начинается TDZ для PI
// console.log(PI); // ReferenceError
const PI = 3.14;
console.log(PI); // 3.14
}
Пример: Function declaration vs function expression
// Function Declaration — поднимается целиком
declared(); // "Я объявлена"
function declared() {
console.log("Я объявлена");
}
// Function Expression — поднимается только var
try {
expressed(); // TypeError: expressed is not a function
} catch (e) {
console.log(e.message);
}
var expressed = function () {
console.log("Я выражение");
};
Типичные ошибки
Утверждение, что let и const вообще не поднимаются — они поднимаются, но в TDZ
Считать, что физически переносятся строки кода, а не происходит работа на этапе создания контекста
Путать поведение function declaration и function expression
Игнорировать разницу между функциональной и блочной областью видимости
Не упоминать, что var инициализируется значением undefined, а let/const — нет


