Hoisting In JavaScript

Dhruv VashistDhruv Vashist
5 min read

During my journey of learning JavaScript I always thought that JavaScript is a weird language(only because I didn't understand the underlying functionality or how JavaScript works and it's fundamentals😅) and one such concept was Hoisting. So, after reading and understanding about it I'm writing this blogpost which aims to provide a clearer understanding as to what is hoisting and how it works.

Introduction

So, let's consider the below example.

    getName();
    console.log(x);
    var x=7;
    console.log(x);

   function getName(){
      console.log("Dhruv");
  }

What do you think will be the output? 🤔 Will it throw any error or not?

This will be output from the above code snippet.

image.png

You might have questions like why it did not throw an error if we are console logging the variable x before declaring and initializing it? (or) why is the guy writing this blog taking too long to explain the damn concept 😂 ? To answer that let's recap on how JavaScript executes i.e. how it creates the execution context and what happens inside them.

So, in the first phase i.e. the Memory creation phase the JavaScript interpreter just skims through the whole code and allocates memory for the variables and methods. So, the reason we are not getting any error is in this Phase-1 as the interpreter skims through the whole code it creates memory for the variable x and assigns a default value to it i.e. undefined in our case. Let's take a look at this from a diagram. This is till line no.2:

image.png

This is because the JavaScript interpreter splits the declaration and assignment of functions and variables: it "hoists" your declarations to the top of their containing scope before execution. So, at first whenever a variable using var is created it attaches themselves to the global object in our case the window object(as we are executing it in browser) and JavaScript hoists the variable at top and assigns a default value as undefined and as a result when the interpreter comes at line no. 3 it will print as undefined as the value of x at that point of time is undefined. Think of what is happening with the below code snippet:

      var x;// x is hoisted at the top with a default value as undefined.
      getName();
      console.log(x);//undefined
      x=7;//Now the same x is assigned the value 7
      console.log(x);//7

      function getName(){
        console.log("Dhruv");
      }

Variable hoisting acts differently on how the variable is declared. Variables in JS are declared using var, const & let.

Variable Hoisting in var

Consider the below example:

console.log(a); //undefined
var a="Yayyyy";
console.log(a);//Yayyy

As we defined in the earlier section that the interpreter splits the declaration and initialization part into two steps like:

var a;
console.log(a); //undefined
a="Yayyyy";
console.log(a);//Yayyy

So, the first console.log() outputs undefined not because the variable is never declared but 'a' is hoisted and given a default value(undefined). Undefined and not defined are two separate things. If you are using an undeclared variable in JS it throws ''ReferenceError: a is not defined".

image.png

That's why it's recommended if you are using var for variable declarations always declare your variable as close to top of the scope as possible.

Variable Hoisting using let and const

Variable hoisting using let and const also behave in the same way in the sense that the interpreter splits out the declaration and initialization part but in the declaration phase it doesn’t assign the variable declared a default value. Rather it will just throw an error “Reference Error: cannot access 'a' be used before initialization”.

console.log(a); // Uncaught ReferenceError: Cannot access 'a' before initialization
let a = 'bar';  // Same behavior for variables declared with const

It hoists the particular variable but can't access it because if you see the error message it's written cannot access 'a' before initialization. the interpreter knows that variable is hoisted but it doesn't assign it a default value hence, the error.

Temporal Dead Zone (TDZ)

image.png

This was one of the most fun topics to read learning hoisting. The Temporal Dead Zone starts from the enclosing scope and is there till the variable is initialized and accessing variable in this Temporal Dead Zone yields error like Reference Error. Consider the below example:

// Start of foo's TDZ
//  foo's TDZ continues here
//  foo's TDZ continues here
//  foo's TDZ continues here
    console.log(foo); // ReferenceError because we're in the TDZ

    let foo = 'foo';  // End of foo's TDZ

So, after the variable is initialized then we can do console.log() and it will work fine. So, if we just swap the last two statements in the above snippet it will work fine as we are accessing the variable foo after it's initialized or not in the TDZ.

image.png

Now the question that can come into your mind is why does Temporal Dead Zone not bother us in case of var. The reason for that is when a variable is declared using var it is hoisted at the top of the enclosing scope and a default value(undefined) is assigned to it and hence as the TDZ starts it also end there itself. Consider the below snippet:


// Start of foo's TDZ and end of foo's TDZ
    console.log(foo); // undefined as foo's TDZ does not exist here.
    var foo = 'foo';  //  foo's TDZ does not exist here.

Function Hoisting in JavaScript

Function hoisting is useful because we can hide the implementation further down the file and only let the reader focus on the signature of the method. When JS scans the code it holds the reference of the function in memory and hence, it's easier to invoke the particular function before creating it.

getName();

function getName(){
console.log("Dhruv");
}

As you have the reference of getName() in the memory you can invoke it before we have written the code for creation of it. If you remember how JS works, it will first skim through the whole code and for functions store the whole function and will add the reference of the function in the memory.

If you want to read about how functions in JS works you can refer here: Execution Context.

Conclusion

I hope you liked this explanation and it was worth your time . This video was particularly helpful for me in writing this blogpost: Namaste JavaScript

Feel free to comment and do reach out to me and let me know if you have any questions.

7
Subscribe to my newsletter

Read articles from Dhruv Vashist directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Dhruv Vashist
Dhruv Vashist

I'm a passionate software developer who thrives on the thrill of learning something new every single day. My journey is all about coding, debugging, and deploying with a sprinkle of creativity and innovation. I'm on a mission to enhance my skills and share my adventures in the tech world with you.