Поиск по сайту
Ctrl + K
Вопросы по JS

Что такое "hoisting" в JavaScript?

Hoisting (поднятие) — это механизм в JavaScript, при котором объявления переменных, функций и классов перемещаются в начало их области видимости перед выполнением кода.

Однако, при поднятии переменные остаются без инициализации, а классы и let/const-переменные находятся в "Temporal Dead Zone" (TDZ) до фактического объявления.


Hoisting переменных

var

Переменные, объявленные с var, поднимаются, но не инициализируются. Их значение по умолчанию — undefined:

console.log(a); // undefined
var a = 10;
console.log(a); // 10

Фактически код интерпретируется так:

var a; // Объявление поднято
console.log(a); // undefined
a = 10;
console.log(a); // 10

let и const

Переменные, объявленные с let и const, также поднимаются, но не инициализируются, поэтому доступ к ним до объявления вызывает ReferenceError:

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

То же самое с const:

console.log(c); // ReferenceError
const c = 30;

Причина — временная зона TDZ (Temporal Dead Zone): переменная существует, но доступ к ней запрещен до явного объявления.


Hoisting функций

Function Declaration (объявление функции)

Функции, объявленные с function, поднимаются вместе с их телом:

greet(); // "Hello, world!"

function greet() {
    console.log("Hello, world!");
}

Так как function greet() полностью поднимается, код работает.


Function Expression (функциональное выражение)

Функции, объявленные через var, ведут себя как переменные:

console.log(sayHello); // undefined
var sayHello = function() {
    console.log("Hello!");
};
sayHello(); // "Hello!"

Поднимается только объявление var sayHello;, но не само присвоение.

Если использовать let или const, произойдет ReferenceError:

console.log(sayHi); // ReferenceError
let sayHi = function() {
    console.log("Hi!");
};

Hoisting классов

Классы в JavaScript поднимаются, но остаются в TDZ, как let и const:

const obj = new MyClass(); // ReferenceError
class MyClass {
    constructor() {
        this.name = "Class";
    }
}

Причина в том, что классы в JS не поднимают свое определение.


Hoisting import

Модули ES6 импортируются до выполнения кода, что делает их доступными сразу:

import { myFunction } from './module.js';

myFunction(); // Можно использовать без проблем

Но импорты всегда должны быть в начале файла.


Итоговая таблица hoisting

ДекларацияДоступ до объявления
var fooundefined
let fooReferenceError
const fooReferenceError
class FooReferenceError
var foo = function() { ... }undefined
function foo() { ... }Работает нормально
importРаботает нормально