Hoisting in JavaScript - An in-depth guide on how hosting works in JavaScript.

Hoisting in JavaScript - An in-depth guide on how hosting works in JavaScript.

Hoisting is one of the most important concept of JavaScript and also most incorrectly understood too. So I tried to make it easy for everyone.

ยท

6 min read

In this blog, I would share my understanding of Hoisting in JavaScript (to be precise we will talk about Hosting in var defined variables and functions)and how I understand this very important concept of JavaScript.

As I am a Java person there are a lot of concepts in JavaScript which doesn't make sense to me like(First class functions, undefined keyword, dynamic behaviour, acronymous behaviour and of course hoisting). But then I started reading and watching content around it and understood it. So will be sharing my learning through this blog.

First thing First, to understand Hoisting we have to have some knowledge of 'How a JavaScript program gets executed' which is a bit weird but it's the magic behind Hoisting.

Note: Everything in Javascript happens inside an 'Execution Context'.


A brief introduction of 'Execution context':

Before going further and understanding the concept of 'Hoisting' we have to understand the execution context. Execution context is a container in which all of the JavaScript programs run. Whenever you run a JS program a 'Global Execution Context' get created and pushed in the Call stack(HW: read about Call stack on your own ๐Ÿคฃ and why JS only has one main Call Stack ). All the code execution takes place inside an 'execution context'.

Note: Every function creates its own 'execution context' and all other things which is not inside a function are a part of the Global Execution context.


How does a JavaScript Program gets executed?

A JavaScipt program gets executed in 2 phases, to be precise the 'execution context' is divided into two parts and in turn two phases:

  1. Memory Allocation phase( Variable Environment) - In this phase JS engine skims through your program and allocated the memory to all of your variables and functions. This happens even before the JS engine enters interpretations of the very first line of code.

  2. Execution phase (Thread of execution): This is the phase where all the operations, assignments, function declaration and function invocation happen. It is in this phase only all your functions and variable get their value assigned.

It is quite confusing and weird right, so let us understand it a bit better with a diagram and taking a small program as our example.

This is our code, sweet and simple:

Test code for better understanding

In this code, we are simply declaring a variable 'num' and assigning it a value '5' at the same time. Alongside it, there is also a function 'test' which simply prints 'hello' when being called on the console.

Now, what I will do is place a breakpoint* before the first line of the code and let's see what happens even before the execution of our program.

So as already discussed the JS engine skims the program even before executing a single line of code, here we can see in the Memory creation phase what values have been assigned to our variable and function.

Thera are 2 scenarios:

  1. For variables: JS engine puts a placeholder called 'undefined' as a value for all of your variables in the 'Global execution context' and attached it to a global object*.

  2. For functions: JS simply puts the whole function as a value for your functions.

I hope you understand what's happening here because the 2 phase execution of JS programs is the reason behind 'Hoisting'. If not let us take one more example and everything will be crystal clear after it.

Let us try to access a variable or function even before defining or declaring it and examine the behaviour in the console.

Reason for this behaviour:

Firstly whenever we try to access a variable declared with the var keyword, we will get an output as undefined.

Although that's not the case with variables defined with const and var keywords. I will write a small article about it because some other concepts applied in those scenarios like Temporal Dead Zone, scoping and all as they aren't attached to the global object like variable defined with var keywords.

Note: If we have declared a function using functions expression then we will get undefined as output when we try to access the function because then the JS engine will take that function as variable only and behave in the same way.

Here is a quick example to showcase that:

You can clearly understand what could have happened right? As I have declared a function using the function expression and tried to access it before its declaration and you can see the results.

  • First undefined comes from line 6 which we talked about previously and the reason behind this is Hoisting itself.

  • The second undefined comes from line 7 because we have declared the function using the function expression and it is in the creation phase and treated as a variable only.

  • The last one is a TypeError which says: add is not a function and if you think it again it is correct, we just learnt that a function defined using function expression is treated as a variable in the Hoisting concept.

Here are some of the key takeaways from these examples:

  1. Whenever someone asks you about Hoisting in javaScript then don't say anything dumb like, it is a concept where the JS interpreter moves the declaration of functions, variables and classes to the top of the file instead tell them about Execution context, global variable and phases of JS program execution.

  2. Variable declared with var keywords behave differently in terms of Hoisting than const and let variables but all of these methods of variable declaration do hoist.

  3. If we declare a function using function expression which is my favourite way of declaring a function then that function will behave the same as if any variable declared with have method would have behaved.


Best Practise:

  1. Always declare all your global as well as function-scoped variables or functions before using them.

  2. Try to use const and let as much as possible and simply forget var exists. This will explicitly tell you the error without sneakily breaking your code.


Resources and Credits:

  1. Namastey Javascript playlist by Akshay Saini: youtube.com/watch?v=pN6jk0uUrD8&list=PL..

  2. The Complete Javascript course by Jonas Schmedtmann: https://www.udemy.com/course/the-complete-javascript-course/

breakpoint*: When we want to debug our program, we can put a debug checker (a breakpoint) at that specific point of the code by simply clicking on the numbered line of that code, as I have done in above mentioned image.

global object: A global object is an object which was provided by the browser to us and gives us access to a lot of build variables and functions. For eg. alert(), prompt() blur() and localStorage and whatnot. It is also most commonly called a *window object. You can go to your console and type console.log(window) and check for yourself.

I hope this article adds some value and gives you some information about this amazing concept of Hoisting in JavaScript. I have just started writing articles and still learning so do comment with your suggestions if you have any. If you like the content then do like and share and I will be publishing another article on 'How hoisting works in const and var defined variables.

If you find any mistake or anything has been explained wrongly do point it out. Thanks in advance!

Signing Off ๐Ÿ’Œ

ย