Temporal Dead Zone (TDZ)
TDZ — промежуток между началом блока и точкой инициализации
let/const, где переменная объявлена в Environment Record, но доступ к ней даётReferenceError.
Что это / Зачем
В отличие от var (который связывается с undefined на фазе создания scope), let/const создаются в специальном состоянии uninitialized (hole). Любое чтение или запись до фактического объявления → ReferenceError: Cannot access 'x' before initialization.
TDZ нужен чтобы:
- Раннее обнаружение багов — обращение до объявления это почти всегда ошибка
- Семантика "временной мёртвой зоны" — defenders argue, что переменная не существует, пока не объявлена
Пример
{
// TDZ для x начинается здесь
console.log(x); // ReferenceError: Cannot access 'x' before initialization
console.log(typeof x); // ReferenceError даже для typeof!
let x = 5;
// TDZ закончился — x доступна
console.log(x); // 5
}
Как реализован в V8
На фазе instantiation Environment Record создаётся с binding x в состоянии uninitialized. Каждое использование let/const в TDZ компилируется Ignition в команду ThrowReferenceErrorIfHole — проверка на hole перед чтением.
var такой проверки НЕ имеет — отсюда разница в производительности (см. источники AsForJS).
// Байткод (упрощённо):
// для `let x`:
LdaContextSlot [x]
ThrowReferenceErrorIfHole [x] // ← проверка TDZ
// для `var x`: ThrowReferenceErrorIfHole отсутствует
Подводные камни
typeof xдля необъявленной переменной даёт'undefined'(без ошибки), ноtypeof xв TDZ даётReferenceError— единственное место в JS, гдеtypeofможет бросить- TDZ работает и для параметров функции:
function f(a = b, b) {}→ ошибка, потому чтоbв TDZ classтоже имеет TDZ (какlet)constбез инициализации —SyntaxError(нельзя оставить hole навсегда)
🎓 Источники
- ⚡ [Why does everyone use var, let and const incorrectly] · AsForJS · 2021-04-11 · YouTube
- Тезисы: TDZ заставляет Ignition генерировать
ThrowReferenceErrorIfHoleна каждое обращение. У var этого нет — это и есть причина "лишнего" кода у let/const
- Тезисы: TDZ заставляет Ignition генерировать
- ⚡ [⎡spec03⎦ Hoisting согласно спецификации] · AsForJS · 2023-11-19 · YouTube
- Тезисы: в спеке слова "TDZ" нет, есть
uninitialized binding. Любое обращение к uninitialized —ReferenceErrorпоGetBindingValue
- Тезисы: в спеке слова "TDZ" нет, есть