Introduction
First of all, let's understand the term 'HOISTING'. Hoisting means lifting up. For example, when we hoist our flag or when a crane lifts something, it's hoisting(lifting up) that thing, Right? Now, before proceeding further, I will recommend you to read my previous blog, because both the blogs are connected to each other and it will help you to understand the concept of this blog very easily. But let's revise a few concepts from the previous blog.
In the previous blog, we have understood that whenever we run our code an Execution Context is created and inside that context, we have two phases - Memory Creation Phase and Code Execution Phase. Memory Creation Phase runs first and allocates memory/space to all the variables
and functions
and after that Code Execution Phase runs and it assigns the actual values to its corresponding variables
. But why I am saying here variables
only, don't worry we will understand it later in this blog.
Variable Hoisting In JavaScript
Now coming back again to the Memory Creation Phase. We know that when we run our code Javascript Engine scans the whole code and allocates memory to all the variables
and functions
. But, in the case of variables
, it assigns with a default value of undefined
in Memory Creation Phase only, even before the execution of our code. Now let's understand all these concepts with the help of examples.
Variable Hoisting: using the keyword var
var exOne = 'I am learning Hoisting in Javascript';
console.log(exOne);
// Output : I am learning Hoisting in Javascript
What do you think, what will be the output? It's simple, Right? It will give I am learning Javascript in the console. Now let's move to the next program.
console.log(exTwo);
var exTwo = 'Programming is fun';
console.log(exTwo);
Now, what do you think, what will be the output? But before giving you the answer I want to remind you of something and that is 'Memory Creation Phase'. We know in Memory Creation Phase, Javascript Engine will allocate memory and the default value undefined
to its variable before executing the program. So, let's find out the answer.
First, let's see the code above, here Javascript Engine will go to line 1
and find console.log(exTwo);
. Now, it finds the variable exTwo
but till now we haven't assigned any values to it and also trying to console log exTwo
, Right? So, it will assign the default value i.e. undefined
to exTwo
. Now, JS Engine will move to line 2
. Here, we are assigning 'Programming is fun' to variable exTwo
, so it will hold this value. Now, JS Engine will move to line 3
, here we are again trying to console log variable exTwo
. Now, it will print 'Programming is fun', because here we have assigned 'Programming is fun ' to variable exTwo
. So our output will look something like this,
//Output :
// undefined
// Programming is fun
In the above program, we tried to console log variable exTwo
before declaring it. But, what if we try to console log the variable exTwo
without declaring it. So, what do think, what will be the output when we run the below code?
console.log(exTwo);
So, here also JS Engine will scan the whole program and it finds exTwo
but there is no declaration for exTwo
, so JS Engine will not assign any memory to it and throws an error.
Uncaught ReferenceError: exTwo is not defined
Difference between undefined and not defined. undefined: we will get
undefined
as an output when we try to access the variable before its being initialized or without initializing the variable. On the other hand, not defined is an error, we will face when we try to access the variable before declaring it.
Think it of as a stranger whom you don't know, will you let him/her in your house, No!, Right? Now let's understand hoisting through the 'let' and 'const' keywords.
Variable Hoisting: using the keywords let
and const
console.log(exThree);
let exThree = 'I love programming';
console.log(exFour);
const exFour = 'Javascript is a weird language';
When we declare variables using keywords let
and const
, it will work as same as the keyword var
. But when we try to access the variable declared with keywords let
and const
before initializing it, it will throw an error.
Uncaught ReferenceError: Cannot access 'exThree' before initialization
Uncaught ReferenceError: Cannot access 'exFour' before initialization
But why do these happen? In the case of the keyword var
, when we try to access the variable before initializing it we get undefined
, but with keywords let
and const
we get an error. This happens because of the 'Temporal Dead Zone'. I will not cover this topic in this blog but don't worry we are going to play more with let
and const
and Temporal Dead Zone in the next blog. Now let's understand hoisting from the eyes of function
.
Functional Hoisting In JavaScript
funcOne();
function funcOne(){
console.log('hi! i am function one');
}
// Output : hi! i am function one
What will be the output? Again, it's very simple, Right? We have used functions
like it before so many times. But how does it possible to access a function even before declaring it. Have you remembered the last line of the second paragraph? So here is the answer, because in the case of functions
, in Memory Creation Phase, JS Engine allocates the memory and the whole code inside that function
as the value. Now when this function
is invoked before or after the declaration of that function an Execution Context is created and in Memory Creation Phase inside this Execution Context, it will simply print the 'hi! i am function one' in the console and after that, this Execution Context will be deleted and the control will be transferred to Global Execution Context. Now if don't understand yet, just simply copy and paste the below code and open the console, you will find your answer.
console.log(funcOne);
function funcOne(){
console.log('hi, i am function one');
}
console.log(funcOne);
You will get output in the console as :
ƒ funcOne(){
console.log('hi, i am function one');
}
ƒ funcOne(){
console.log('hi, i am function one');
}
Now, you know how we are able to access the function even before declaring/initializing it. But, what if we write the same function
using the fat arrow
or anonymous function. So, let's find out our answer. We have our code below,
// Using fat arrow function
console.log(funcOne);
var funcOne = () => {
console.log('hi, i am function one');
}
console.log(funcOne);
funcOne();
// Using anonymous function
console.log(funcOne);
var funcOne = function(){
console.log('hi, i am function one');
}
console.log(funcOne);
funcOne();
And here I am asking for your answer again, so what will be your answer. Yes, you guessed it right, here funcOne
will act as a variable
and it will output in the console as :
undefined
ƒ (){
console.log('hi, i am function one');
}
hi, i am function one
So, in both(using fat arrow and anonymous functions) the programs above, we have funcOne
as a variable. So when JS Engine will scan these programs, it will allocate memory as well as the default value of undefined
for line one. Now it will move to the next line and will assign the whole function to variable funcOne
. In the second-last line, we are console logging the variable funcOne
which holds the entire function in it, so it will print the whole code inside that function. Now, in the last line we are invoking funcOne
which will now act as a function rather than a variable and again the whole cycle will repeat.
So, that's it guys in this blog. In the next blog, we will talk about the variable declared using keywords let
and const
, and also we will travel around the Temporal Dead Zone
. Don't worry we will not die there. So, till then see you in the next blog.