Uncovering the Mystery of Hoisting in JavaScript

Uncovering the Mystery of Hoisting in JavaScript

The Key to Unraveling Variable and Function Scope

Hoisting is one of the confusing topic of javascript and the most asked one in the interviews. I have covered the in-depth what, how, and why of hoisting in this blog.

Note: Before proceeding further I highly recommend you read my previous blog Understanding the Javascript Engine: How Javascript Works which covers topics that will be mentioned in this blog and will help you understand hoisting better.

Definition

Hoisting is a behaviour in javascript which lets you access variables or functions before they are declared.

Example

A couple of examples showing the hoisting behaviour of variable and function:

console.log(x); // Output: undefined
var x = 1;

Here variable x is accessed before its declaration without giving any error.

console.log(userName); 
// Output: ƒ userName() { console.log("ashwincodes") }

function userName() {
    console.log("ashwincodes");
}

Here function userName is accessed before its declaration and it returned its function definition itself.

What happens behind the scenes?

Since this behaviour is a little weird and confusing let’s dive deep to see why this happens.

In the last blog, I explained how Javascript works and how Global Scope is created that helps the javascript engine to run the program. I highly recommend reading that blog first before proceeding ahead with this blog.

Now that you have read that blog let’s see how execution context plays a big role in hoisting.

First, let’s see what happens in Global Scope using a non-hoisting code example:

var num = 10;

function userName() {
    console.log("ashwincodes");
}

userName(); // Output: ashwincodes
console.log(num); // Output: 10

We have added a breakpoint on the first variable to see what happens in the global execution context.

We can see before the code even start executing our variable num is allocated a value in the global scope(also known as window object in the browser) as undefined.

As I explained in my last blog the Global Scope is created before the code is run which runs the memory allocation and code execution phases.

Before any of the code is executed javascript skims through the code and allocates memory for every variable and function in the memory component. That is why we see num: undefined in the global scope.

Similarly, if we added a breakpoint to the function it gets allocated its own definition in the global scope before any code ran.

Now, let's tweak our code a bit that shows hoisting behaviour clearly:

From what we learned above about memory allocation and code execution phases we can now connect the dots and see that even though userName() function is called before declaring the function it still runs because javascript allocated its memory in global scope before any code ran.

Similarly, num: undefined is allocated in the memory before the code is executed, and since num is already allocated a value in the global scope console.log(num) returns undefined.

Conclusion

Hoisting is the most common question asked in the interviews.

Most developers try to understand hoisting before understanding how the Global Scope and the Execution Context work. That is why I mentioned above also to read my previous blog on the same. It will help you understand hoisting 10x faster without any doubt left.

I hope this explanation helped you understand what is happening under the hood of hoisting.

Ref: Hoisting in JavaScript (variables & functions) | Namaste JavaScript Ep. 3