Hoisting in JavaScript explained visually ๐Ÿ”ฅ ๐Ÿ˜

Hoisting in JavaScript explained visually ๐Ÿ”ฅ ๐Ÿ˜

ยท

5 min read

Featured on daily.dev

Developers often have a love-hate relationship with JavaScript because sometimes it doesn't work as expected. Learning JavaScript fundamentals and it's quirks can assist developers in debugging and writing clean code. This blog post aims to explain one such peculiarity, i.e. hoisting using animated gifs ๐ŸŒŸโœจ. After reading this blog, you will be one step closer to becoming a Rockstar Developer ๐ŸŽธ๐Ÿ˜Ž.

getStarted.avif

Execution of JavaScript code.

Before understanding the concept of hoisting letโ€™s first learn how javascript will run code behind the scene through an example.

var a = 2;
var b = 4;

var sum = a + b;

console.log(sum);

In this simple example, we initialize two variables, a and b, and store 2 and 4, respectively. Then we add the value of a and b and store it in the sum variable. Let's see how JavaScript will execute the code in the browser ๐Ÿค–.

When the JS first receives our code, it will create an execution context. Execution context will first scan through all the code, and allocate memory to all the variables and functions. For variables specifically var, JavaScript will store undefined in the memory, and for functions, it will keep the entire function code reference in memory.

execContext1.1.gif

Now that we have scanned and allocated memory to the code, we can execute the code. JavaScript will again start going through the whole code line by line.

As it encounters var a = 2, it assigns 2 to 'a' in memory. Until now, the value of 'a' was undefined.

Similarly, it does the same thing for the b variable. It assigns 4 to 'b'. Then it calculates and stores the value of the sum in memory which is 6. Now, in the last step, it prints the sum value in the console and then destroys the global execution context as our code is finished.

execContext1.2.gif

If you want to learn more about execution of code in JavaScript, I wrote an article about it on the dev community.

Link: https://dev.to/narottam04/how-javascript-works-visually-explained-269j

Hoisting in var

To understand hoisting in a variable defined with var, let's take the example we took in the execution of code. However, in this example, we're going to print the sum at the beginning, not at the end.

console.log(sum);

var a = 2;
var b = 4;

var sum = a + b;

The above code would throw an error in other programming languages, but not in JavaScript.

code2.png

As we saw in the section on the execution of code, when JS first receives our code, it will create an execution context. Execution context will first scan through all the code, and allocate memory to all the variables and functions.

execContext1.1.gif

Now after scanning the code it will start the execution of the code line by line. In the first line, javascript checks the value of sum in memory and prints undefined as an output.

Now, as it encounters var a = 2, it assigns 2 to 'a' in memory. Until now, the value of 'a' was undefined.

Similarly, it does the same thing for the b variable. It assigns 4 to 'b'. Then it calculates and stores the value of the sum in memory which is 6.

hoisting2.2.gif

If we console log after we calculate the sum letโ€™s see the output.

code-2.4.png

Initially, it will print undefined, after computing the sum, it will print 6. This peculiarity in javaScript is called hoisting. Letโ€™s learn hoisting in let, const keywords and functions.

Hoisting in let and const

When we refer to a variable declared with the var keyword before its declaration, it simply returns its default value: undefined! However, as demonstrated in the previous example, this can sometimes result in "unexpected" behavior.

Therefore, ES6 introduced two new JavaScript keywords to combat this unexpected behavior: let and const. These two keywords are Block Scope. To keep this article concise we would be learning more about the scope in another blog.

Letโ€™s see the hoisting in let and const through an example.

console.log(a);
console.log(sum);

var a = 2;
let b = 4;
const c = 6;

const sum = a + b + c;

So letโ€™s start with the execution of code again, when JS first receives our code, it will create an execution context. Execution context will first scan through all the code, and allocate memory to all the variables and functions. I know I've mentioned this multiple times, but it's important ๐Ÿ˜….

As opposed to var where undefined is stored in memory, let and const variables are uninitialized.

hoisting1.1.gif

After scanning the code it will start executing the code line by line. The first line will print the value of โ€˜a' i.e. undefined in the console. But when we try to access a let and const keyword before initialization, a ReferenceError gets thrown whenever we try to access uninitialized variables. Uninitialized variables cannot be accessed since they are in a temporal dead zone.

Temporal dead zone simply means we don't have access to the variables before declaration.

code-4.png

If we try to print the value of โ€˜bโ€™ instead of the sum the result would be the same.

code4.1.png

The value of the sum must be printed once the deceleration of the value to the variable is complete.

code4.2.png

Here is the visualization of the execution of code.

hoisting3.gif

Hoisting in function

When javaScript begins scanning code and comes across a function, it stores the function's reference in memory. It is the reason why we can invoke the function before we have created it. Letโ€™s see it in action through an example.

printSum(4,5)

function printSum(a,b){
    const c = a + b;
    console.log(c);
}

The output of the following code will be.

code5.png

Let's try to visualize, first JavaScript will scan the code, it will encounter a function in the 3rd line, and it will add a reference of the function to the memory.

hoisting4.gif

Javascript will now run the code line by line. It comes across a function on the first line. When a function is executed in javascript, it creates a new execution context within our global execution context. Consider the function execution context to be a mini execution context, with its memory and a location to execute the code in the function.

Read more about how functions execute code in this blog post.

hoisting5.gif

Once all the code inside the function is executed, the execution context of the function is destroyed.

Reference

https://media.giphy.com/media/xUPOqo6E1XvWXwlCyQ/giphy.gif

I hope this post was informative. ๐Ÿ’ช๐Ÿพ Feel free to comment or reach out to me if you have any questions.

Did you find this article valuable?

Support Narottam Sahu by becoming a sponsor. Any amount is appreciated!

ย