Что такое hoisting (поднятие)?
Почему функцию можно вызвать выше её объявления, а переменная при этом undefined.
Hoisting (поднятие) — поведение, при котором объявления переменных и функций как будто «поднимаются» в начало своей области видимости ещё до выполнения кода.
Как это работает
Движок JavaScript обрабатывает код в два прохода. Сначала он «регистрирует» все объявления (создаёт переменные и функции), и только потом выполняет код сверху вниз. Поэтому имена уже существуют к моменту запуска — но значения присваиваются позже.
Функции поднимаются целиком
Function declaration (function foo() {}) поднимается полностью, вместе с телом. Поэтому её можно вызвать выше объявления.
console.log(sum(2, 3)); // работает до объявления!
function sum(a, b) {
return a + b;
}
Вывод:
5
var поднимается без значения
var поднимается, но присваивание остаётся на месте. До строки с присваиванием переменная равна undefined — не ошибка, но и не значение.
console.log(name); // существует, но ещё пустая
var name = "Аня";
console.log(name);
Вывод:
undefined Аня
Function expression НЕ поднимается как функция
Если функцию присвоить переменной, поднимется только переменная (как var/let), а не функция. Вызвать её до строки присваивания нельзя.
try {
greet();
} catch (e) {
console.log(e.name + ": greet ещё не функция");
}
var greet = function () {
return "Привет";
};
console.log(greet());
Вывод:
TypeError: greet ещё не функция Привет
До присваивания greet равна undefined, а вызов undefined() даёт TypeError.
Памятка по поднятию
| Что объявлено | Поднимается? | Доступ до объявления |
| function declaration | да, с телом | работает |
| var | да, без значения | undefined |
| let / const | да, но в TDZ | ReferenceError |
| function expression | как переменная | undefined / ошибка вызова |
Зачем вообще знать про hoisting
На собеседовании за этим вопросом обычно стоит не желание услышать определение, а проверка: понимаете ли вы, почему один и тот же приём (function vs const fn = () => ...) ведёт себя по-разному. Практический вывод, который стоит озвучить: function declaration удобна, когда хочется свободно располагать функции в файле; стрелочные функции в const заставляют объявлять до использования, что делает поток данных линейным и читаемым. А var-поднятие — частый источник багов вроде «переменная внезапно undefined», поэтому переход на let/const с их TDZ как раз превращает такую ошибку в явный ReferenceError.
Итог
- Hoisting — это «двухпроходная» обработка: сначала объявления, потом выполнение.
- Function declaration поднимается целиком и доступна выше объявления.
varподнимается какundefined; function expression вызвать заранее нельзя.