Hoisting and TDZ in Javascript
Javascript can be tricky to understand sometimes because of how it works. Concepts like Hoisting and TDZ are one of those "Javascript-special" items on the tricky concepts menu. But once we know what it is, it makes all the sense why it is. So, let's get started with our today's topic - Hoisting and TDZ in Javascript.
What is Hoisting?
Hoisting is basically Javascript's default behaviour to move all the variable declarations to the top if its scope.
Which means, you can use the variable before declaring it and it won't throw you any error. See below example:
console.log(myName) // prints "undefined"
var myName = "Omkar"
Someone who comes from a different coding language background will expect this code to throw error. But, above code runs fine without any errors. Seems "wrong", doesn't it? This works because before actually running the code the JS engine moves (hoists) all the declarations at the top - this is called "Hoisting".
While hoisting the variables, the variables defined with var
are initialized to undefined
by default. Which is why, when we print the myName
variable before initializing it with its value "Omkar", it prints "undefined".
This is not the case for variables defined with let
and const
.
Variables defined with let
and const
does get hoisted. But, they are not initialized with undefined
value by default like var
. If you try to use these variables before their declaration, it will throw you a Reference Error saying the variables are not initialized yet. (In case of const
, it will throw Syntax Error as seperating out declaration and initialization for const
variables is not allowed). See below example:
const printData = () => {
console.log(varName); //this will print "undefined"
console.log(letName); // this will throw ReferenceError
var varName = 'Omkar';
let letName = 'Jadhav';
};
printData();
This happens because until the varialbles defined with let
and const
are not declared, they are in Temporal Dead Zone (TDZ)
Temporal Dead Zone (TDZ)
TDZ is for the variables defined with let
and const
. The TDZ for a variable starts at the beginning of the containing block and ends at its declaration.
Note that the TDZ for that variable ends when it gets declared and not when its initialized.
What's the difference between declaration and initialization ?
See below example:
let name; // 1 --> Declaration
name = "Omkar"; // 2 --> Initialization
let fullName = "Omkar Jadhav"; // 3 --> Declaration & Initialization at same time
As we can see above, we are declaring the variable "name" at line 1. Declaration of a variable reserves some memory for that variable.
At step 2, we are initializing the name variable with value "Omkar".
These two steps can be done at same time like its done for variable fullName
at line 3.
const printData = () => {
// "firstName" is in TDZ
// "firstName" is in TDZ
// "firstName" is in TDZ
// "firstName" is in TDZ
// "firstName" is in TDZ
let firstName; // Declaration: TDZ for firstName ends here
console.log(firstName) // It will print undefined
firstName = "Omkar" // Initialization
console.log(firstName) // This will print "Omkar"
};
printData();
In above example, the TDZ for variable "firstName" starts at the start of its block. It stays in TDZ until it gets declared. If it gets used in TDZ, it will throw Reference error.
Once it gets declared, the TDZ for "firstName" ends. It will no longer throw error past this point when it gets used. But, its value would be undefined
until it gets initialized with some other value, just like var
.
How to avoid getting into TDZ errors?
Simply, we should practice declaring all the required variables at the top of the scope itself. This will make sure you won't get Reference Error.
For more detailed information regarding Temporal Dead Zone, check out this amazing article written by Kealan Parr.
That's all for today. Thanks for reading! Will meet you again with some other blog. Till then, happy coding!