Hoisting in Javascript ๐Ÿ”ฅ

ยท

4 min read

Hoisting in Javascript ๐Ÿ”ฅ

Before I start explaining Hoisting, try to guess the output of the following code without running in the console -

console.log(x);
getName( );

function getName( ) {
   console.log("John Doe");
};

var x = 5;

So the output would be -

console.log(x); // undefined
getName(); // John Doe

If you didn't get this right, read on to know how hoisting works in Javascript.

So there are two types of Javascript developers out there. Those who have got the above output right and actually understood hoisting in javascript and those who think they have understood hoisting.

Through this blog, I will try to clear the concept of hoisting and make you really understand how hoisting works in javascript. Are you ready?

Gif

The definition as per mdn doc is Hoisting refers to the process whereby the interpreter allocates memory for variables (those varaibles decalred with var) and function declarations prior to execution of the code.

In order to understand this, we need to understand how JS code is executed?

When a script file is loaded in the browser, the javascript engine creates an Execution context. This execution context runs in two phases. The first phase is the memory creation phase and the second phase is the code execution phase. For example, you had a script file with just one line of code with a variable named x and a value of 8.

   console.log(x); // undefined
   var x = 8;

So when this line of code runs, an execution context will be created. In the memory creation phase, x will be stored with a value of undefined and that is the reason we see undefined in the console when we try to access it before declaring it. What if the variable was declared with let/const. Lets look at an example

    console.log(x); //Reference Error: x is not defined
    console.log(y); //Reference Error: y is not defined

    let x = 8;
    const y = 9;

    console.log(x); // 8
    console.log(y); // 9

Variables declared with let and const are also hoisted, but the variables declared with let/const are not initialized with a default value of undefined. Until the line in which they are initialized is executed, any code that accesses these variables will throw a reference error. That is why the console prints the value of x & y as 8 & 9 respectively when we log them after they are initialized.

In order to understand how let/const variables work, we need to understand Temporal Dead Zone. I will write the blog on it soon and link it here.

Now let's understand how function hoisting works.

Let's see a quick example.

    getName( ); 
   // undefined ? John Doe ? cannot access getName before initialization?

   function getName( ) {
      console.log("John Doe");
   }

Guess the output before running it in the console. What do you think will be logged?

Well, John Doe will be logged. The reason is, JS will save the entire function while allocating memory to the function getName and it is hoisted to the top of all the variables and because of this we can access functions even before declaring them.

This whole phenomenon of hoisting happens only with variables declared with var and function declarations and not with function expressions

So what happens when we declare a function inside a variable as a function expression and try to access it even before declaring the function?

Lets see an example for the same.

getName( );

var getName = ( ) => {
   console.log("John Doe");
}

Will it be undefined as we are accessing the variable before it is initialized ?

Think over it?

Gif

Well the answer is TypeError: getName is not a function.

Gif

I know you must be shocked to see the output as an error instead of undefined as we saw in earlier examples. Let me help you clear the concept.

Remember, memory is allocated to all the variables in the first phase before the code starts executing. Since getName is a function expression, undefined will be stored as it behaves like how a variable is declared with var. And now when we try to invoke getName( ) whose value is undefined in the memory, it will throw an error saying

Hey, getName is not a function.

Had we declared getName as a function declaration, then the name would be printed as expected. Here is an example

getName( ); // John Doe

function getName( ) {
   console.log("John Doe");
};

Now, I hope you have understood how hoisting works in JS and yes JS is a little unpredictable at times.

Before we go here's a JS quote I came up with while learning JS -

You really don't know Javascript, until you have run it at least once !!

Let me know if you have any doubts in the comment section. You can also reach out to me on twitter

The detailed video explanation can be found here