As JavaScript is getting increasingly popular and extensively used, people are utilising its ability to make both server and client-side applications that are fast and use fewer resources of a machine.
In my last post, we talked about a JS engine, its Execution context, phases and how things work inside a Javascript Engine. For this Post, we will talk about the most important concept of JS which is known as “HOISTING”.
In javascript, the variable declarations and how value is assigned to that variable work differently from other programming languages.
As we have already talked about how the JS engine works in the earlier post. it will be now easy to understand the concept of hoisting
So now let’s get started with an introduction hoisting in laymen's terms.
What is Hoisting ?
“It is a mechanism inside JS due to which all variable and function declarations are moved at the top of the scope before the code is executed”.
It does not matter where the variables or functions are declared the JS engine moves all the declarations at the top of their respective scopes before the code execution phase. The assignments stay at their place.
Now you will wonder what is this scope now.
For now, consider scope as a container where your code is present.
For Example:
function container() {
var num1 = 4; // num1 scope is limited to container function
}
In the above example, the scope of num will be limited to function (locally scoped) as it is contained inside it. If your variable or function is present at the parent level i.e not inside any function it means it is globally scoped ie. it can be accessed from anywhere (depends on how it is declared).
Types of Hoisting
There are two types of hoisting:
- Variable hoisting
- Function Hoisting
1. Variable Hoisting:
In variable hoisting, the variable declarations are moved on top of their scope while the process is still inside the memory creation phase.
The hoisting working differs from the way that a variable is declared. We have three ways to define a variable: let
const
and var
.
For every variable declaration, the variable is first assigned with a default value of “undefined”
before the code execution phase where the actual value is given to the variable.
var declaration:
For Example: let's consider this code snippet
console.log("before num ==> ", num);
var num = 10;
console.log("after num ==> ", num);
Here is how the JS engine will treat this code:
1. num = undefined // memory creation phase
2. before num ==> undefined // execution phase
3. num = 10 // execution phase
4. after num ==> 10 // execution phase
This is how the basic var
declared variables work.
In the first step, the JS engine will look for all variable and function declarations. In our case, it will find only “num1”
and move it to the top of its execution context (if it is inside any function it will go to the top of that function). Memory is allocated to the variable and the value is assigned as "undefined"
.
point to be noted that our variable is in global space here and it is bound to the global object due to the var
declaration.
After the memory creation phase
code starts executing from top to bottom.
At the first line it will find console.log(“number is = ”, num);
as the value of num
is undefined
right now it will print undefined
In the second step, the variable gets initialised with a new value i.e 10
Again it will come to the log line 4 and print after num is = 10
as it is now being assigned an actual value.
This is how var declared hoisting works. Now let's see how to let and const hoisting works.
let & const declaration:
For Example: let's consider this code snippet
console.log("before num ==> ", num);
let num = 10;
console.log("after num ==> ", num);
run this code you will get:
console.log(num);
^
ReferenceError: Cannot access 'num' before initialization
You are wondering Why this error came up?
The let and const variables are hoisted and assigned a value of undefined in a separate memory space & are in a Temporal Dead Zone.
They are not bound to the global object of JS instead they have their separate memory space where they are hoisted.
The JS engine knows that they exist but cannot access their value, and these are available for access only when they are initialised with a value else they are not accessible and will give a reference error.
For Example:
as you can see in the image, the var declared variable a_var
is bound to the global object so it can be accessed before initialisation. While the let and const declarations: b_let
and c_const
are in a separate script memory phase space but they are hoisted.
Temporal Dead Zone:
So basically from the time of hoisting till the time of value initialisation the let and const variable declarations are not accessible this time period is known as the “Temporal Dead Zone”.
2. Function Hoisting:
Functions in JS can be declared in two ways
- Function Declaration
- Function Expressions
Function Declaration:
In JS, the function declarations are stored as it is inside the memory in the memory creation phase. So when we call the function which is declared using legacy function declaration syntax it is accessible i.e we can call it before it is initialised. This means that function declarations are hoisted.
Here you can see in the above image, I have added a breakpoint at the start of the script which means the function is not yet started executing (only the memory phase is completed) still you can clearly see inside the global object the allow
function is attached. Now let's just run the whole code
here you can see that we have called the allow
function just before the actual function declaration but it is still printing allowing...
this shows that function declaration are also hoisted.
The difference between variable and function hoisting is just that the variables are first assigned an undefined
value whereas the function is stored as a whole inside the memory.
Function Expression:
In function expression, we store the function inside a variable which is then used to call the function.
As we know variables are hoisted and assigned an undefined value in it. Unlike function declarations, function expression hoisting work like variable hoisting. The first variable holds an undefined
value in the memory creation phase and then the function is assigned to that variable.
Due to this if we call the function before actually assigning it to the variable it will throw a Type Error: allow is not a function
which basically means the function expressions are not hoisted.
Arrow functions work in the same way as function expressions.
Tip:
You can try all of the above-given examples in your browser by opening inspect window in the source panel.
Conclusion:
JavaScript hoisting occurs during the creation phase of the execution context that moves the variable and function declarations to the top of the script.
The JavaScript engine hoists the variables declared using the let keyword, but it doesn’t initialise them as the variables declared with the var keyword.
The JavaScript engine doesn’t hoist the function expressions and arrow functions.
I Hope now you have a better understanding of what is JS Hoisting and what its types are.
If you like the content please share it with your friends, colleagues, and coding buddies. Have a nice day ❤️
Top comments (3)
Сongratulations 🥳! Your article hit the top posts for the week - dev.to/fruntend/top-10-posts-for-f...
Keep it up 👍
Good work Mihir.
thanks Harshit