Temporal Dead Zone

Temporal Dead Zone

This phrase seems intimidating, right? Let's make it easy for you and start by breaking the term into pieces. Temporal means something that is temporary, Dead means something that is lifeless, and Zone in programming terms can be interpreted as the memory. The Timespan between the creation of a variable and its declaration is called the Temporal Dead Zone.

This term came into existence in ES6 with the introduction of let and const to help developers write better code and make debugging easy, by telling them that they are accessing some data before defining it.

Before ES6 there was no other way to declare variables other than var, and if var variables are accessed before declaration it would give us undefined instead.

console.log(b);// output -> undefined
var b=100;

let and const declarations are both block-scoped, which means they are only accessible within the { } surrounding them.

There's a common misconception that TDZ means let and const do not hoist. This is an inaccurate, or at least slightly misleading, claim. They definitely hoist. Read more about hoisting here

var a = 100;
if (true){
   console.log(a);// a is in TDZ
   let a = 10;
}
output-> ReferenceError: Cannot access 'a' before initialization

What's going to happen with the console.log(..) statement? If let a didn't hoist to the top of the scope, then the console.log(..) should print 100, right? At that moment, it would seem, only the outer a exists, so that's the variable console.log(..) should access and print.

But instead, the console.log(..) throws a TDZ error, because, the inner scope's a was hoisted. What didn't happen (yet!) was the auto-initialization of that inner a; it's still uninitialized at that moment, hence the TDZ violation!

So to summarize, TDZ errors occur because let/const declarations do hoist their declarations to the top of their scopes, but unlike var, they defer the auto-initialization of their variables until the moment in the code's sequencing where the original declaration appeared.

The TDZ can also be created for default function parameters.

function createTDZ(a=b, b) {
// some code here
}

createTDZ(undefined, 1); 
// output -> ReferenceError

As arguments are evaluated from left to right, the evaluation of variable a tries to access variable b before it has been parsed by the JS engine. The function arguments are all inside the TDZ until they are parsed.

Another Example:

By the way, "temporal" in TDZ does indeed refer to time not position in code. Consider:

let a = f(); 
const b = 2;
function f() { return b; } // b is in the TDZ

Even though positionally the return referencing b comes after the const b = 2; declaration, timing-wise the f() function is invoked before the let statement is encountered, while b is still in its TDZ! Hence the ReferenceError.

Takeaway:

To avoid TDZ, always make sure you define your let and const at the top of any scope. Shrink the TDZ window to zero (or near zero) length, and then it'll be moot.

Did you find this article valuable?

Support Bhavika Tibrewal by becoming a sponsor. Any amount is appreciated!