What is Hoisting in JavaScript ?

Introduction

Hoisting is one of the most important concepts in JavaScript. Let's look at an example before we move forward:

function sum (a,b) {
  return a+b;
}

console.log(sum(5,10));

It is quite clear that the output of the above console log will be 15. Let's do some changes to the above example. Let's move the console log to the top.

console.log(sum(5,10));

function sum (a,b) {
  return a+b;
}

Now, what will be the output? Well, let me tell you that the answer will again be 15. But isn't this weird? We are able to access the sum function even before we've initialized it. You may be wondering about this behavior of JavaScript. Well, this is happening because of Hoisting. Let's deep dive into this.

despicable-me-minions.gif

What is Hoisting?

In simpler terms, Hoisting is a phenomenon where we can access the functions and variables in JavaScript even before initializing it. This is why we're getting the output as 15 in the above example. We now know what happened in the previous example, but We still don't know how it happened. So, let's move on to the behind-the-scenes of how Hoisting works.

How Hoisting works?

We know that whenever we run a JavaScript program, an execution context is created. This creation of execution context happens in two phases where memory allocation is the first phase. I mentioned only the first phase because the answer to our question is there only. What I mean is in the memory allocation phase, before the program starts executing, memory is allocated to variables and functions. In the case of functions, JavaScript allocates a copy of the function in the memory. This is why when we ran the function sum, we got the desired result as JavaScript had stored the copy of the function in phase 1 of the execution context creation phase.

We now have a basic understanding of Hoisting. Let's tweak the above example a little more. We know that we can access functions before we initialize them. So, let's convert the above function sum into an arrow function:

console.log(sum(5,10));

var sum = (a,b) => {
  return a+b;
}

Now, this is an interesting change that we've made because now, the program won't give us 15 as an output. Instead, it's going to result in an error stating:

TypeError: sum is not a function

Wait, the program was supposed to print 15 in the console, right? Due to the memory allocation phase, it must store the copy of the function. Why JavaScript didn't allocated a copy of the function in the memory this time? I'm sure you might have this question in your mind. Don't worry, I'll explain. It happened because functions and variables are hoisted quite differently from each other. Yes, I know this is an arrow function, but it behaves like a variable. To understand this clearly, we need to understand how variables are hoisted in JavaScript.

olafs-frozen-adventure-olaf.gif

Variable hoisting in JavaScript

During the memory allocation phase, variables are allocated memory with the placeholder undefined. This means only in the case of normal functions, does the copy of the function gets created. Now, Consider the same example:

console.log(sum(5,10));

var sum = (a,b) => {
  return a+b;
}

Since sum is an arrow function and behaves as a normal variable, it gets allocated in the memory as undefined. Thus, we get a Type Error as we're calling an undefined variable instead of a function. Do note that JavaScript does not hoist const/let variables, only variables defined with the var keyword are actually hoisted. This means if we replace var with let/const in the above example, We still get an error but this time it will be a different error stating:

ReferenceError: sum is not defined

Conclusion

Thanks for reading, I hope that now you have a clear understanding of what hoisting is and how it works behind-the-scenes so next time someone mentions it you can understand exactly what they mean. Understanding how hoisting works is incredibly important since it can be a powerful tool for code organization when defining functions.

the-office.gif