Hoisting In JavaScript

Hoisting In JavaScript

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.