Published: November 2nd, 2020
While digging deeper into the concepts of ES6, I stumbled across the term "Temporal Dead Zone". I was curious and found out that I was unknowing of the term itself, but knew the concept of it. I didn't run into the issues too often, but it is absolutely helpful to know why it occurs and how to avoid it. So follow me on my journey through the Temporal Dead Zone.
To get it right off the bat:
The Temporal Dead Zone describes the state, when variables are unreachable.Anonymous
The term isn't mentioned in the EcmaScript Language Specification but is used from us programmers to give the child a name.
So what does that mean? And why haven't I encountered this when writing code in the past (before ES6).
Variable declaration and hoisting
Let's start with an extremely simplified example:
var myVar = 'Hello World'
myVar to the top of its scope. Since we declared it with
var it and creates a global property. We then try to log
myVar before we declare it which logs us
undefined, the default initialization value for
var. Then we initialize its correct value and log it again. This time we log
So far so good. Our code doesn't break and we can just live with the
Let's step it up and write this in ES6 (so let's use
let instead of
let myVar = 'Hello World'
myVar. This time we declared it with
let which doesn't create a global property, since
const) are block scoped. Both are hoisted into the Temporal Dead Zone. We then try again to log
myVar but Ooops! This throws an
Uncaught ReferenceError: can't access lexical declaration 'myVar' before initialization and breaks our code!
On ExploringJS, you can find a really nifty table, showing all the variants how variables can be declared and how they are hoisted.
|let||Temporal Dead Zone||Block||No|
|const||Temporal Dead Zone||Block||No|
I found contradictory statements about the hoisting of
const. Some say they are not hoisted at all, some say the are but into the TDZ.
I follow the later one, because a short example shows in my opinion that they are indeed hoisted; to the Temporal Dead Zone.
console.log(myHoistedLet); // Uncaught ReferenceError: can't access lexical declaration 'myHoistedLet' before initialization
let myHoistedLet = 'Awesome!';
Temporal Dead Zone explained
As quoted above, the state between the declaration of a variable with
Both variables are bound to their blockscope. So the cycle looks a bit like this:
- Entering the scope of the variable
- Bind space for the variable (Hoisting), the variable is not initialized -> ReferenceError
- If there is a declaration initialize the value if given, if not default to
constis a bis special here, it must have an initializer since it is immutable (not 100% true but for this example close enough)
console.log(myVar); // ReferenceError
let myVar; // TDZ ends, myVar is initialized without a value
console.log(myVar); // undefined because of the default behaviour
myVar = 'Awesome!'; // initializer is called with a value
console.log(myVar); // Awesome!
Why is there a Temporal Dead Zone?
Plain and simple: For debugging and code stability.
The block scoping of
const helps with globals pollution plus the addition of a thrown
I am a big fan of failing fast and early, so postponing errors from declaration to the usage is not a good practice. And it also is time consuming. Ever had a bug where the result just is not be correct? Debugging hundreds of lines of code just to find a false declaration of a
var? Been there, debugged that. No bueno! Failing already at the declaration of the variable would have prevented that error.