Understanding Temporal Dead Zone in JavaScript

Yomesh Gupta
JavaScript in Plain English
5 min readJun 14, 2020

--

A photo of a Macbook with code editor application open
Photo by Blake Connally on Unsplash

Temporal Dead Zone is an advanced and interesting topic in JavaScript. To understand what it is and how things work, we need to understand different ways of variable declaration in JavaScript.

Var, Let, and Const

ES6 brought a lot of new features to the language and one of them was the ability to define variables using different keywords which have subtle differences among them (https://www.ecma-international.org/ecma-262/6.0/#sec-let-and-const-declarations).

We can declare variables in three ways

var name = "Yomesh";
let surname = "Gupta";
const profession = "Software Engineer";

Let us understand what are the differences between these three.

Scoping

In the most simple terms, scoping is the area in which a variable is accessible. Scoping of a variable is controlled by the location of its declaration. Let us consider an example.

function init() {
var firstname = "Yomesh";
console.log(firstname); // Yomesh
}
console.log(firstname); // Error

In the above code snippet, variable firstname is declared inside the function init i.e. anywhere inside this function we can get or set the value of the variable. However, accessing the same variable outside the function would lead to ReferenceError: firstname is not defined.

Types of Scoping

We have three types of scoping, namely, Global, Function, and Block scoping. Now you must be thinking what does this all exactly means? Think no more, it is example time!

// Global Scope
var firstname = "Yomesh";
function sayName() {
console.log(firstname); // firstname is accessible here
}
function nestedSayName() {
function sayNameNow() {
console.log(firstname); // firstname is accessible here
}
sayNameNow();
}
sayName(); // console logs "Yomesh"
nestedSayName(); // console logs "Yomesh"

In the above code snippet, the variable firstname is declared outside the functions. Any variable which is declared outside of a function will fall into Global scope and is accessible to all parts of the code.

// Function Scope
function sayName() {
var firstname = "Yomesh";
console.log(firstname); // firstname is accessible here
function sayNameNow() {
// firstname is accessible here and we can update it.
firstname = "Ronaldo";
console.log(firstname); // Ronaldo
}
sayNameNow();
}
sayName();

In the above code snippet, variable firstname is declared inside the function sayName. It is scoped to that function i.e. it can be used inside the sayName function or any nested functions. All variables declared via var are function scoped.

// Block Scope
function sayName() {
var condition = true;
if (condition) {
let firstname = "Cristiano";
const surname = "Ronaldo";
console.log(firstname, surname); // Cristiano Ronaldo
}
console.log(firstname, surname); // ReferenceError
}

In the above code snippet, variables firstname and surname are declared inside the scope created by the if code block. The first console.log statement logs the value correctly as variables are accessible in that scope. However, the second console.log throws an error because variables simply don’t exist there.

Declaration & Initialisation

A variable declaration introduces a new identifier. JavaScript interpreter creates a new variable during the creation phase.

var name = "Yomesh"; // allowed
var name = "Cristiano"; // allowed
let surname = "Gupta"; // allowed
let surname = "Ronaldo"; // Error
const profession = "Software Engineer"; // allowed
const profession = "Footballer"; // Error

Any variable declared via var can be re-declared as many times as we want. However, let and const can be only declared once in their respective scope. Variables are declared via var have the default value of undefined. Variables declared via let and const exist but without a value and cannot be accessed before they are assigned (More on this later).

Binding to the Global Object

var firstname = "Yomesh";
let surname = "Gupta";
const profession = "Software Engineer";
// Yomesh Gupta Software Engineer
console.log(firstname, surname, profession);
// Yomesh undefined undefined
console.log(window.firstname, window.surname, window.profession);

Variables declared via var keyword in the global scope are automatically attached to the Global Object i.e. window in the browsers. The same is not the case with let and const.

Understanding Temporal Dead Zone

JavaScript engine runs through our code in two phases — the Creation phase and the Execution Phase. In the first phase, the engine goes through the code and allocates memory for the variables.

console.log(firstname); // undefined
var firstname = "Yomesh";

In the same phase, the variables declared via var are assigned the value undefined and that is why in the above code snippet you will get the value of the variable firstname as undefined. This is also what we know as “Hoisting”.

console.log(firstname); // ReferenceError
let firstname = "Yomesh";

In the case of the variables declared via let and const, they are also allocated memory but they are not assigned the value undefined initially i.e. variable declarations do hoist but they throw an error till initialized. Let us consider an example.

/*
Since variables are hoisted
it would be equivalent to

let firstname;
Beginning of the temporal dead zone*/
console.log(firstname); // ReferenceError as accessed in the TDZ
function init() {
...
}
function processing() {
...
}
var surname = "Gupta";
var profession = "Software Engineer";
let firstname = "Yomesh"; // Ending of the temporal dead zone
console.log(firstname); // Yomesh

As you can see that there exists a region (temporal dead zone) for the variable firstname which begins from the place where the variable is hoisted as in its scope is created till the place where the variable is initialized. Temporal Dead Zone is a good way to indicate bugs in the code. Accessing variables before declaration is often a root cause of errors.

In the Execution phase, variables are assigned their actual values and it is perfectly fine to use them afterwards.

// Accessing `name` here before execution phase assigns the value to the variable would throw a ReferenceError due to TDZ.
// console.log(name);
const name = "Yomesh";console.log(name); // Yomesh | Perfectly fine to use here

Temporal Dead Zone is everywhere. We considered the examples related to variable declarations but it also exists in newer features like Default Parameters.

I hope this article helped you in some way and gave you more clarity. Let me know your views in the comments or by clicking here. To test your knowledge, try the following question: https://code.devtools.tech/questions/s/what-would-be-the-output-based-on-temporal-dead-zone---qid---aDXxcPUD7LZNdjBCJYo8

--

--