Skip to main content

Temporal dead zone (TDZ)

The TDZ (temporal dead zone) is the stretch of time from the start of a variable's scope to the moment it is actually initialised, during which the variable cannot be accessed. Put simply, it is a "dead zone" in which the variable already exists (the engine has registered it) but has not been initialised yet, so trying to use it raises an error.

Theory

TL;DR

  • The TDZ is the period between creating a variable's binding and initialising it.
  • It applies to let, const and class.
  • Accessing a variable inside its TDZ throws a ReferenceError.
  • var is hoisted too, but it is initialised to undefined straight away, so it has no TDZ.
  • typeof does not save you in the TDZ: it throws a ReferenceError as well.
  • Every block { ... } creates its own scope and therefore its own TDZ.
  • The purpose is safety and predictability: you cannot use a variable before it is declared.

Quick example

javascript
console.log(a); // ReferenceError let a = 10;

What happens:

  1. JavaScript knows a exists before the code runs, at the point where the lexical environment is created.
  2. But until the line let a = 10;, the variable sits in the TDZ.
  3. Any attempt to touch it in that zone throws a ReferenceError.

How it differs from var

javascript
console.log(x); // undefined var x = 10; console.log(y); // ReferenceError let y = 20;

The difference:

  • var variables are hoisted and initialised with undefined;
  • let and const are hoisted as well, but not initialised, and until initialisation they sit in the TDZ.

So hoisting applies to both forms; what differs is whether the binding gets a starting value.

The TDZ inside a block

javascript
let a = 1; { // the TDZ for b starts here console.log(a); // 1 // console.log(b); // ReferenceError let b = 2; // end of the TDZ console.log(b); // 2 }

Every block { ... } creates a new scope, and the let and const variables inside it have their own dead zone up to their initialisation.

The same holds inside a function: the TDZ is in force from the moment you enter its scope until the declaration line.

javascript
function foo() { console.log(bar); // ReferenceError let bar = "Hello"; } foo();

The TDZ and typeof

The typeof operator is safe for a variable that does not exist at all, but it does not help in the TDZ.

javascript
console.log(typeof x); // "undefined" console.log(typeof y); // ReferenceError let y = 10;

This is one of the very few situations where typeof throws: for a completely undeclared name it returns "undefined", while for a name in the TDZ it raises an error.

The TDZ and class

Classes obey the TDZ too:

javascript
const obj = new MyClass(); // ReferenceError class MyClass {}

A class declaration is hoisted, but it sits in the TDZ until its declaration line, exactly like let and const. That is why a class, unlike a function declaration, cannot be used above the place where it is declared.

Why it exists

The TDZ is a safety and predictability mechanism. It stops you using a variable before it is genuinely ready.

If let behaved like var, it would be easy to hit unpredictable bugs caused by undefined that surface far away from their real cause. With the TDZ, the error appears exactly where the problem is.

Visually:

javascript
{ // the variable already exists in memory, but is unreachable: this is the TDZ console.log(x); // ReferenceError let x = 5; // end of the TDZ, the variable is initialised console.log(x); // 5 }

Summary

FeatureDescription
What the TDZ isThe period between creating a variable and initialising it
Where it appearsFor let, const, class
What happens on accessReferenceError
Why it existsIt prevents using variables before their declaration
Difference from varvar is initialised to undefined, let/const are not

Common mistakes

  • Saying that let and const "are not hoisted". They are hoisted, they are just not initialised, and that is precisely what creates the TDZ.
  • Relying on typeof as a safe check. For a variable in the TDZ it throws a ReferenceError.
  • Confusing ReferenceError: Cannot access 'y' before initialization (the TDZ) with ReferenceError: y is not defined (no such variable at all).
  • Using a class above its declaration on the assumption that it behaves like a function declaration. Classes have a TDZ.
  • Forgetting that the TDZ is tied to position in the code, not to time: a function call written above the declaration but executed later works fine.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.