Variables, hoisting, and the temporal dead zone in JavaScript
By: Gaurav Awale
Tags: Advanced Javascript, Web Development, JavaScript, Hoisting, ES6

Photo by Christopher Robin Ebbinghaus on Unsplash

Introduction:

Variable hoisting is one of the simplest but still misunderstood concepts in JavaScript. There are still a few of us who feel that in Javascript variable declaration is physically moved to the top of the function block. Although conceptually it is much simpler to visualize and understand the variable being physically moved to the top, that is not how it happens.

Let's understand this with an example, consider the code below

function test() {

console.log(myVar);

var myVar = 10;

console.log(myVar);

}

test(); // Output

> undefined

> 10

Understanding the output

The simple way: The variable declarations are hoisted, and that essentially means the above code gets interpreted as

function test() {

var myVar;

console.log(myVar);

myVar = 10;

console.log(myVar);

}

test();

The detailed way: Javascript executes code in two phases, the creation phase, and the execution phase.

The creation phase: Whenever the function call happens, the JS engine creates a function scope and in that stores all the variable declarations and initializes them to undefined.

The execution phase: Here, when we try to access the variable myVar for the first time, the engine can see the variable name in the memory (stored in the creation phase) with the value undefined. Thus we can see undefined printed in the console. And once the value is assigned to myVar, 10 is printed.

But what happens with let and const? Do they not get hoisted? Do they not get created in memory during the creation phase?

Let’s try the same code with let:

function test() {

console.log(myVar);

let myVar = 10;

console.log(myVar);

}

test(); // Output

> VM94:2 Uncaught ReferenceError: Cannot access 'myVar' before initialization

at test (<anonymous>:2:14)

at <anonymous>:6:1

We got a reference error.

This happens because the variable myVar is not reachable until it is declared. Such a state, where the variable is present in the scope but is unreachable, is called Temporal Dead Zone.

So, does this mean that when we use let and const, the variable is not created in the memory during the creation phase?

Actually, it does get created in the memory during the creation phase, the only difference between let and var is that the variable is not initialized with anything if it is let, while var is initialized with undefined.

To confirm this, let's look at the code below:

function test() {

console.log(typeof myUndefinedVariable);

console.log(typeof myVar);

let myVar = 10;

}

test(); // Output

> undefined

> VM114:3 Uncaught ReferenceError: Cannot access 'myVar' before initialization

at test (<anonymous>:3:10)

at <anonymous>:6:1

The above output proves that the JS engine knows that myVar is present in the scope, but it is just not accessible.

There is not a single scenario where we need to access a variable before it is declared, and if there is, it must be incorrect.

So, to catch errors at an early stage and prevent the nuisance that might occur because of the variables declared after their use, the concept of the temporal dead zone was introduced in ES6.

“Luck is not as random as you think. Before that lottery ticket won the jackpot, someone had to buy it.” –Vera Nazarian

References: