Hoisting: поднятие переменных и функций

Что такое Hoisting? 🏗️

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

Но будь осторожен: поднимается только объявление, а не инициализация! Это может приводить к неожиданным результатам.

console.log(message); // undefined, а не ошибка!
var message = "Hello, hoisting!";

Как работает Hoisting? 🤔

1. С переменными var

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

console.log(name); // undefined (но не ReferenceError!)
var name = "Alice";

Фактически, интерпретатор видит это так:

var name;          // Поднято вверх
console.log(name); // undefined
name = "Alice";    // Присваивание остаётся на месте

Важно:

  • let и const тоже поднимаются НО не инициализируются (ReferenceError).
  • var создаёт глобальную или функциональную область видимости, а let/const — блочную.

2. С функциями

Function Declaration (объявление функции) поднимается целиком!

sayHi(); // "Hi!" — работает, даже если вызов перед объявлением!

function sayHi() {
  console.log("Hi!");
}

Но Function Expression (функциональное выражение) — не поднимается!

sayHello(); // TypeError: sayHello is not a function
var sayHello = function() {
  console.log("Hello!");
};

Здесь переменная sayHello поднята, но её значение (undefined) ещё не функция.


Hoisting в let и const 🚧

Переменные let и const недоступны до объявления (в отличие от var). Они находятся в "временной мёртвой зоне" (TDZ).

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

💡 Совет: Всегда объявляй переменные до использования (let/const), чтобы избежать TDZ.


Как запомнить разницу? 🧠

Таблица: Hoisting в var, let, const и функциях

Тип Поднимается? Инициализируется Пример ошибки
var ✅ Да undefined undefined
let ✅ (но TDZ) ❌ Нет ReferenceError
const ✅ (но TDZ) ❌ Нет ReferenceError
Function Declaration ✅ Да Вся функция
Function Expression ❌ Нет ❌ Нет TypeError / ReferenceError

Практика: типичные ловушки Hoisting 🎯

Пример 1: var в цикле

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// Вывод: 3, 3, 3 (а не 0, 1, 2!)

Почему?
- var создаёт одну переменную на всю функцию/глобальную область.
- Решение: используй let (блочная область видимости).

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// Вывод: 0, 1, 2 ✅

Пример 2: Переопределение функции

func(); // "Вторая"

function func() {
  console.log("Первая");
}

function func() {
  console.log("Вторая");
}

Почему?
- Function Declarations поднимаются, и последнее объявление побеждает.


Итоги: правила Hoisting 🏆

  1. var поднимается c undefined.
  2. let/const поднимаются, но недоступны до объявления (TDZ).
  3. Function Declaration поднимается целиком.
  4. Function Expression подчиняется правилам переменных (var/let/const).

🔥 Совет от Данилы Бежина (из его YouTube-канала):

"Всегда используй const по умолчанию, let — если переменная меняется, var — никогда. Так код будет предсказуемым!"

Попробуй применить эти знания в своём коде — и увидишь, как легко избежать скрытых багов! 🚀

Скрыть рекламу навсегда

📘 VK Видео — обучение без ограничений

Все уроки доступны без VPN, без блокировок и зависаний.

Можно смотреть с телефона, планшета или компьютера — в любое время.

▶️ Смотреть на VK Видео