Table of contents
Introduction
Can you predict the output of these snippets of JavaScript code? Would the error occur?
const hyundai = new Car();
class Car {
constructor(color) {
this.color = color;
}
}
// Error or not?
myFunc();
function myFunc() {
console.log("a");
}
// Error or not?
console.log(myFunc(3, 5));
let myFunc = (a, b) => a + b;
// Error or not?
console.log(str);
let str = "JS"
// Error or not?
The answer is that the last two will have the ReferenceError. Even though your answer was correct, if you guessed it or if you do not know why the ReferenceError occurs, this article will be helpful to you.
In this article, I will be talking about Hoisting and Temporal Dead Zone (TDZ) as well as the differences between var, let and const.
var, let, const, function Declaration
Whenever you declare a variable, there will be three stages involved.
Declaration - Registering a variable in the scope.
Initialization - Allocating memory and creating a binding for the variable. In this phase, the variable is assigned a value
undefined
.Assignment - Assigning a value by using the assignment operator(=).
For the var
variables, both the declaration and initialization phases occur at the same time, which means:
var a; // declaration and initialization
console.log(a); // no error. prints undefined
Although I haven't assigned any values, it already has an undefined value.
You can do something like this:
console.log(a); // prints undefined. no error.
var a;
When declaring a function, the stages are like this. All the three phases happen at the same time.
So there is no error when you do this:
a(); // no error.
function a() {
console.log("Jay's Dev Blog");
}
Please have a look at the diagram above. Notice that the declaration and initialization phases do not happen at the same time. More importantly, there is something called Temporal Dead Zone between the two stages. It indicates that "Accessing variable throws ReferenceError".
*Note. The life cycle diagram is the same for const
, too.
Let's have a look at this code:
console.log(letVar); // Temporal Dead Zone
console.log(constVar); // Temporal Dead Zone
let letVar;
const constVar;
Unlike var
, this results in ReferenceError because the area above letVar and constVar are said to be a temporal dead zone. So, what is the temporal dead zone and why is it said to be the TDZ?
Temporal Dead Zone
Unlike var
, the declaration and initialization do not occur at the same time, which means there are no values (even undefined) assigned in the memory spaces for both letVar
and constVar
variables. Therefore, the JavaScript engine cannot refer to those two variables.
Declarations that are affected by the TDZ
let - explained above
const - explained above
super()
class
default function parameter
class
let car = new Car(); // TDZ
class Car {
constructor(color) {
this.color = color;
}
}
You can create a new instance after the declaration of the class. Otherwise, the JavaScript engine cannot refer to the class.
super()
class MiniVan extends Car {
constructor(color, power) {
this.power; // TDZ
super();
}
}
The super() must be called before this
keyword. Before calling super() this binds to TDZ
Default Function Parameter
let a = 5
function myFunc(a = a) {
return a * a;
}
console.log(myFunc()); // ReferenceError
When you want to use the default function parameter, avoid using the same variable name as the default parameter.
Better code:
let num = 5;
function myFunction(a = num) {
return a * a;
}
console.log(myFunc()); // 25
Declarations that are NOT affected by the TDZ
var - explained above
function - explained above
These two are explained above. They are not affected because the declaration and initialization phases occur at the same time, so undefined
is assigned in the memory spaces. This means that the JavaScript engine can refer to the variable or function.