What is Hoisting In JavaScript?

What is Hoisting In JavaScript?

Definition :

Hoisting is a phenomenon in JavaScript by which you can access the variables and functions even before we have initialized them. Yeah, you heard it right... :) it will not throw any error.

Let us take a simple example

Can you tell me What is the output of this program?

var a = "Hello";
function getMessage(){
    console.log("Hello from function");
}

getMessage();
console.log(a);

Yes, you are right pretty simple one right.....

Output:

image.png

Now we will just tweak the program

getMessage();
console.log(a);
var a = "Hello";
function getMessage(){
    console.log("Hello from function");
}

can you guess the output of this... if you are from a java background(Just like me :) ) you may say that there will be a compile-time error ... but you are wrong this is JavaScript and Javascript has a special concept called hoisting through which it can access the variables before initialization itself.

so the output of this program will be

image.png

So there is no error. But there is something called "undefined" we will see what exactly it means below

Now we will change the program again like below.

getMessage();
console.log(a);

function getMessage(){
    console.log("Hello from function");
}

Yeah now you guessed it right ... Now it will throw an error like this.

image.png

But why it is saying "Not defined" now why not in the previous example. In the previous example, the output was "undefined" now it is "not defined"... what is happening here whether "undefined" and "not defined" both are not equal ??

You got all these questions ?? :) Don't worry I was also confused and frustrated when I learned this concept first... We will now see what is happening under the background and why we are seeing these different outputs

So basically Everything in Java Script happens inside an Execution Context. So now what is it actually ?... Assume it as a big container or box where all the Javascript program runs.

This execution context contains two components and these are created in two Phases

  1. Memory Component or Variable Environment
  2. Code Component or Thread of Execution

In the first phase, Javascript skims through the whole program and allocates memory to the variables and functions, and assigns a value "undefined" to the variables but copies the function as it is.

In the second phase, Javascript again skims through the whole program and executes it

We will take our code as an example and see how the background process runs

var a = "Hello";
function getMessage(){
    console.log("Hello from function");
}

getMessage();
console.log(a);

In our program

  1. We have a variable "a" So Javascript sees this and allocates memory to the variable "a" and assigns a special value called undefined to this(As "a" is not yet given any value)

  2. We have a function getName() so Javascript sees this and allocates memory to our function and copies the whole function code to the memory space

the execution context looks like this

image.png

Now we will move into the second phase which is called Code Execution Phase

Here As soon as it encounters
var a = "Hello" it assigns the value to the variable "a" Now the value of variable a moves from "undefined" to "Hello".

Now our Execution context looks like this

image.png

By Now you may have got a hint on How Hoisting works...So in our program when we first wrote

var a = "Hello";
function getMessage(){
    console.log("Hello from function");
}

getMessage();
console.log(a);

we declared "a" at the starting line and we have console logged it at the last line of the program so we got output as expected.

But when we tweak the program

getMessage();
console.log(a);

var a = "Hello";
function getMessage(){
    console.log("Hello from function");
}

Here we are console logging the variable at the starting line of the program itself. so before even executing the first line of the program memory has been allocated to the variable inside the Global Execution context with special value "undefined". so when you are executing the first line you got output as "undefined" instead of throwing an error.

This is the beauty of the Hoisting.

But What about functions why it kept printing the correct value ??

If you followed the post correctly I have told during memory creation phase variables will be assigned with special value "undefined" and functions will be copied as it is. so before even executing the first line memory got allocated to getMessage function inside the global execution context and it is copied as it is... so whenever you are calling the function (getName();) it automatically prints the value...

yes now that you have understood the concept of hoisting we will now see some more examples

Can you tell me the output of this program?

console.log(a);
console.log(b);
let a = 100;
var b = 1000;

if you would be thinking the output of the above program will be

output: undefined; undefined;

Then you are wrong, The output of this code will be

image.png

wait but why ?? don't the variable already been hoisted inside the execution context ?? then why we are seeing this error ?? ufff... so much confusion this JS is...

you may be thinking like this isn't it?

Don't worry...... :) I will help you understand...

From ES6 Javascript has introduced new features some of them are declaring variables with let and const... so whenever in your program if you have declared some variable using let or const these variables will be allotted in separate memory space, not inside the global space. so that's why you are seeing an error in the previous program

so if we tweak the above program like below

console.log(b);
let a = 100;
console.log(a);
var b = 1000;

Now the "a" variable is declared when the "console.log(a)" statement is executed so there won't be any error the output of this code will be:

image.png

Now that you have learned what is "let" and how it is hoisted differently we will deep dive into some core concepts

let vs const vs var

As I have already told you whenever you declare a variable with let or const it will not be stored inside the Global Execution memory Space. a new different reserved space is used for them so whenever JS tries to log the "a" value it didn't find in the global memory space and it threw an error

Temporal Dead Zone:

What is this new term ?? It is the time when the let or const variable is hoisted and till it has initialized with some value. The duration between them is called the temporal dead zone. so if you see the below code snippet

image.png

here the variable is initialized in line 3. so whenever the Js code is executing line 1 this hasn't been assigned a value. once it executes line 3 the temporal dead zone ends and a value of 100 is put inside the "a".So the phase from hoisting the variable till it got assigned with some value this phase is called the temporal dead zone. the temporal dead zone ends in this example after line 3

so if you are trying to access a variable during the temporal dead zone it gives you a reference error that's why you got the error previously.

cool right... so you have understood now what is hoisting and how it behaves differently with let or const.

I hope this post clarified most of the confusing behaviors of javascript

Quick Recap

We have learned the following in this post

  1. How JavaScript Code Executes in the background?
  2. What is Execution Context and what are the different phases of it?
  3. What is Hoisting in JavaScript?
  4. How it is different with let or const?
  5. what is a temporal dead zone?

The Concepts Mentioned above are referred to and learned from the Namaste Javascript series Created by Akshay Saini On YouTube. This series is highly recommended for everyone who wants to understand the core concepts of Javascript