Temporal dead zone (TDZ)
TDZ (temporal dead zone), це проміжок часу від початку області видимості змінної до моменту її фактичної ініціалізації, коли до неї не можна звертатися. Простіше кажучи, це «мертва зона», у якій змінна вже існує (зареєстрована рушієм), але ще не ініціалізована, і спроба її використати призводить до помилки.
Теорія
TL;DR
- TDZ, це період між створенням зв'язування для змінної та її ініціалізацією.
- Діє для
let,constіclass. - Звернення до змінної в TDZ кидає
ReferenceError. varтеж підіймається, але одразу ініціалізується значеннямundefined, тому TDZ не має.typeofу TDZ не рятує: він теж кидаєReferenceError.- Кожен блок
{ ... }створює власну область видимості, а отже і власну TDZ. - Призначення механізму, безпека й передбачуваність: не дати скористатися змінною до її оголошення.
Швидкий приклад
console.log(a); // ReferenceError
let a = 10;Що відбувається:
- JavaScript знає про існування
aще до виконання коду, на етапі створення лексичного оточення. - Але до рядка
let a = 10;змінна перебуває в TDZ. - Будь-яка спроба звернутися до неї в цій зоні кидає ReferenceError.
Відмінність від var
console.log(x); // undefined
var x = 10;
console.log(y); // ReferenceError
let y = 20;Різниця:
- змінні
varпідіймаються (hoisting) і ініціалізуються значеннямundefined; letіconstтеж підіймаються, але не ініціалізуються, і до моменту ініціалізації перебувають у TDZ.
Тобто hoisting стосується обох форм; відрізняється лише те, чи отримує зв'язування початкове значення.
TDZ усередині блока
let a = 1;
{
// TDZ для b починається тут
console.log(a); // 1
// console.log(b); // ReferenceError
let b = 2; // кінець TDZ
console.log(b); // 2
}Кожен блок { ... } створює нову область видимості, і змінні let та const усередині нього мають власну «мертву зону» до своєї ініціалізації.
Те саме працює й у функції: TDZ діє з моменту входу в її область видимості й до рядка оголошення.
function foo() {
console.log(bar); // ReferenceError
let bar = "Hello";
}
foo();TDZ і typeof
Оператор typeof безпечний для змінної, якої взагалі не існує, але в TDZ він не рятує.
console.log(typeof x); // "undefined"
console.log(typeof y); // ReferenceError
let y = 10;Це одна з небагатьох ситуацій, коли typeof кидає виняток: для повністю неоголошеного імені він повертає "undefined", а для імені в TDZ, помилку.
TDZ і class
Класи теж підпорядковуються TDZ:
const obj = new MyClass(); // ReferenceError
class MyClass {}Оголошення класу підіймається, але перебуває в TDZ до рядка оголошення, точнісінько як let і const. Саме тому клас, на відміну від оголошення функції, не можна використати вище за місцем оголошення.
Навіщо це потрібно
TDZ, це механізм безпеки та передбачуваності. Він не дає використати змінну до того, як вона справді готова.
Якби let поводився як var, ми б легко ловили непередбачувані помилки через undefined, які виявляються далеко від місця справжньої причини. З TDZ помилка виникає рівно там, де є проблема.
Візуально:
{
// змінна вже існує в пам'яті, але недоступна: це TDZ
console.log(x); // ReferenceError
let x = 5; // кінець TDZ, змінна ініціалізована
console.log(x); // 5
}Підсумок
| Особливість | Опис |
|---|---|
| Що таке TDZ | Період між створенням змінної та її ініціалізацією |
| Де виникає | Для let, const, class |
| Що стається при зверненні | ReferenceError |
| Навіщо потрібна | Запобігає використанню змінних до їхнього оголошення |
Відмінність від var | var ініціалізується значенням undefined, let/const ні |
Типові помилки
- Казати, що
letіconst«не підіймаються». Вони підіймаються, просто не ініціалізуються, і саме тому виникає TDZ. - Покладатися на
typeofяк на безпечну перевірку. Для змінної в TDZ він кидаєReferenceError. - Плутати
ReferenceError: Cannot access 'y' before initialization(TDZ) зReferenceError: y is not defined(змінної немає взагалі). - Використовувати клас вище за його оголошення, розраховуючи на поведінку оголошення функції. Класи мають TDZ.
- Забувати, що TDZ прив'язана до позиції в коді, а не до часу: виклик функції, який фізично стоїть вище оголошення, але виконується пізніше, спрацює нормально.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.