cft

Secrets of HOISTING in JavaScript revealed!

We’ll be going too deep in JavaScript, so fasten your belts VISITOR, your journey is about to start.


user

Shivam Bhasin

2 years ago | 5 min read

Hey visitor! Whats’up? Let me guess, “Why is this not working?”, or, “How did this work?”. IKR, perks of being a JavaSript developer. But today I’m on a mission to reveal the mystic SECRETS of one of the most popular MAGIC trick of JavaScript, HOISTING.

We’ll be going too deep in JavaScript, so fasten your belts VISITOR, your journey is about to start.

Let’s get confused!

See the following three cases and how JavaScript has responded to them differently.

  1. In the first case variable i and function getName are declared first and then used. This is regular stuff that we do in most of the programming languages.
  2. In the second case i and getName are declared after being used. This is not allowed in other pl’s and would give a runtime error but with JavaScript, this is allowed. Just note that i has value undefined in it.
  3. In the third case, i is not declared anywhere in the program and hence there is a reference error stating that i is not defined.

//CASE 1

var i = 10;

function getName(){

console.log("Shivam Bhasin");

}

console.log(i);

//10

getName();

//Shivam Bhasin//CASE 2

console.log(i);

//undefined

getName();

//Shivam Bhasin

var i = 10;

function getName(){

console.log("Shivam Bhasin");

}

//CASE 3

console.log(i);

//Reference Err: i is not defined

getName();

function getName(){

console.log("Shivam Bhasin");

}

In case 2, JavaScript already knew that there is a variable i declared, just it’s value is undefined yet, but i is initialized by us in the 3rd line. So somehow JavaScript moved the declaration in line 3 to the top without assigning it the value 10.

Also note that getName do get executed and printed “Shivam Bhasin”. Again, JS knew everything about the function before reaching the declaration of it.

A console.log(getName) in CASE 2, just before getName is declared, will give the following output. This is as if JavaScript has the complete code of the function in the reference to it.

f getName(){

console.log("Shivam Bhasin");

}

However, in case 3, i is not defined by us anywhere in the code. So JavaScript doesn’t know about it and hence threw an error on our face that ‘hey man! where did this ‘i’ come from?’

This is what everyone’s been calling Hoisting. I got this from W3 schools:

Hoisting is JavaScript’s default behavior of moving all declarations to the top of the current scope.

Okay, we got that all our variable and function declarations move to the top of our current scope, but the question is do they really move up? Or there’s something else JavaScript is doing BTS.

BTS(Behind the Scenes — JavaScript)

Before the code starts executing, JavaScript goes through all our code and allocates memory to all the variables and functions. Yes, even when a single line of code is not executed, JavaScript has information about the variables and functions we’ve declared in our code.

Before execution, it creates a Global Execution Scope which is basically 2 phases, Memory Phase and Code Phase. We’re interested in Memory phase today. This is where all our variables and functions are stored before even the first line of code is run. It is provided for us to use as a Global Object.

Memory phase is a key value store. Following is an illustration of this statement.

Picture from dev.to

Consider the follwoing example:

console.log(i);

//undefined

getName();

//Hey Visitor!

console.log(getName);

//f getName(){ console.log("Hey Visitor!"); }

var i = 10;

function getName(){

console.log("Hey Visitor!");

}

Now before the first line of code is executed, JavaScript goes through the code and creates an object Global like below:

Global: {

i: undefined,

getName: f () { //body of the function },

//Other fields in the object

}

You know this Global object, right? No? You’ve used things like window.alert(). Ever wondered, where are these coming from. Yes, you are right! All these functions are provided by JavaScript and put for you to use in this Global object.

In case of variables, it stores undefined and in case of functions, it stores the complete function body. Yes all functions are stored completely in the scope. The object Global, is basically the Global Execution Scope.

So now when JavaScript starts executing code and encounters line 1 i.e console.log(i); ,it know about i because it is in the Global Object, and hence prints undefined. Similarly with the function getName, which get executed because it’s whole body is stored in the global scope.

Now consider the following case:

getName();

//Hey Visitor!

console.log(i);

//Reference Err: i is not defined

function getName(){

console.log("Hey Visitor!");

}

In this case, JavaScript will again create a Global Object like:

Global: {

getName: f () { //body of the function },

//Other fields in the object

}

Here, while executing the code, when JavaScript encounters line 2, i.e console.log(i);, it couldn’t find i in the global scope and hence throws an error i is not defined as in we haven’t declared i anywhere in our code and JavaScript doesn’t know about it.

What about functions?

So far we know that there is a Global Execution Scope which holds the globally scoped variables and functions. Now consider the following case:

console.log(getName);

// f getName() { //body of function }

console.log(i);

//Reference Error: i is not defined

console.log(getEmail);

//Reference Error: getEmail is not defined

function getName(){

var i = 10;

function getEmail(){

console.log("my@email.com");

}

}

In this case JavaScript again goes through our code and creates a global object like:

Global: {

getName: f getName() { //body }

//other fields in the object

}

But in this case both i and getEmail are inside the getName execution context and not in the global scope. This is because every function in JavaScript has it’s own execution context. Consider the complete program as a global function which is put under the GEC.

Note that function execution context is created during execution of that particular function and not before that.

Now see the following scenario:

console.log(getName);

//f getName() { //body of function }

function getName(){

console.log(i);

//10

console.log(getEmail);

//f getEmail() { //body of function }

var i = 10;

function getEmail(){

console.log("my@email.com");

}

}

In this case a global execution scope is created with getName in it. During execution it encounters line 2 and then creates a new getName execution context. This will have it’s own Memory Phase and it’s own global object which will look something like:

getName: {

i: undefined,

getEmail: f getEmail() { //body of function }

}

This scope is limited to the getName execution context and can’t be accessed from anywhere else. Similarly in the case of getEmail function. A new EC will be created when it will be excuted which will be limited to be accessed inside it only.

The execution order is maintained by Call Stack. In the start JS Engine pushes the GEC in the stack and starts executing the code. On encountering a function, it creates a new function oriented EC and push it to call stack. When the function gets executed completely, it pops the EC from the Call Stack and returns the control to the GEC.

So now whenever someone asks what is Hoisting in JavaScript, don’t just say it’s a behaviour of moving the declarations up.

Explain them the Global Execution scope and how JavaScript allocates memory to all variables and functions before starting to execute code.

There is an explanation to every magic there is in JavaScript. Just be curious enough to find the real cause. That’s how things will really get clearer.

I hope you got value from this article. Don’t think twice before leaving your comments for any doubts or discussions.

Until next time, VISITOR!

Upvote


user
Created by

Shivam Bhasin

Simplifying things since childhood. Writes about JavaScript, application development, and self-help.


people
Post

Upvote

Downvote

Comment

Bookmark

Share


Related Articles