In Depth Guide On Hoisting In JavaScript
Tags: javascript, programming, tutorial
Published: 2022-11-06 18:33:25

In this article we will deep dive into hoisting concept in JavaScript. Before we start let's brush up some programming fundamentals.

###Programming Fundamentals

Computer program is just a set of instructions given to the computer to execute. We write programs in high level language (Python, JavaScript, etc.) which is easily understood/read by humans but computers do not understand this high level language. For computers to understand our program, it has to be converted into low level code. So in order to perform this functionality, languages use `Compilers` and `Interpreters`. Compilers and Interpreters take human readable code and convert it to computer readable machine code.

#####Difference between Compilers and Interpreters :

Compiler, scans the entire program in one go and translates it as a whole into machine code.

Where as Interpreter, translates program one statement at a time. Before interpreting next statement, previous statement is executed.

Therefore, compiled languages are faster than interpreted languages as compiled language overall execution time is less compared to interpreted language.

##### Some examples of compiled and interpreted languages are:

Compiled languages : C, C++, Go, Rust, etc.

Interpreted languages : Python, Ruby, PHP, etc.

Now, coming back to JavaScript. Let's check whether JavaScript is interpreted or compiled.

So according to Google and MDN docs, JavaScript is an interpreted language.


![JavaScript is interpreted language](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p3d19et1musa8hmoqxge.jpeg)

This means that JavaScript code is executed line by line, top to bottom.

### Hoisting in JavaScript

Now that we know JavaScript is interpreted language, let's try to solve below problem.

```
console.log(platform)

var platform = "Dev"
```

Let’s try to execute the code line by line in our mind, same as the interpreter would do.

1st line is console.log(platform).

This should give “Reference Error: platform is not defined” because as per interpreter there is no as such variable called platform.

But you will be amazed to know that the correct output is "undefined". Wondering how? 🤔

This is where concept called `JavaScript Hoisting` comes into picture.

According to MDN docs,

_"JavaScript Hoisting refers to the process whereby the interpreter appears to move the declaration of functions, variables or classes to the top of their scope, prior to execution of the code"._

Do you really think that the interpreter takes our code and tosses it up before execution? 🤔 Let's dig in more deeper.

Getting output `undefined` is weird, this means that our variable is declared but not initialised. This also means that the interpreter somehow knows what's happened in next line 🤯. Interpreter here is showing some glimpses of behaviour like a Compiler. 

The real reason behind this is that JavaScript is just-in-time compiled before it’s interpreted. Because of which concepts like hoisting and lexical scoping exist. In this compilation phase, all variables and functions in program is assigned with their appropriate scope.

So, the best way to think about this is that all declarations, both variables and functions, are processed first and scope is assigned to them, before any part of your code is executed. Because of this, interpreter knows about the declaration even before it starts execution. 

Now that we know JavaScript code is parsed before any execution begins then why does JavaScript spec say that variable and function declarations are moved to the top of their scope, before the code is executed? 

To maintain simplicity, so that we can just think about the program as if it's executed by the JS engine in a single pass, top-to-down approach. Moving forward we will also understand examples with this ideology.

Now let's understand how hoisting differs in `var`, `let` and `const` variables.

###Hoisting in `var` variables

```
console.log(a); // undefined
var a = 5;
```

As we see in above example that `console.log` prints `undefined` and not `ReferenceError` this is because after hoisting, the above program behaves as:

```
var a;
console.log(a);
a = 5;
```
Here we can see that `var` declaration is hoisted at the top of the program.

###Hoisting in `let` and `const` variables

Hoisting in `let` and `const` variables is little different compared to `var` variable hoisting.

```
console.log(a);
// ReferenceError

let a = "Hello";
```

when we run the above code, we get `Reference Error : Cannot access 'a' before initialization`. From this error we can notice that the variable `a` is defined in the scope but it cannot be accessed before initialization.

So the main catch is that, with variables declared with `var` keyword are automatically initialised to undefined at the top of the scope whereas variable declared with `let` and `const` keywords are not initialised. 

###Hoisting in function declarations

```
greet(); // Hello

function greet() {
    console.log("Hello");
}
```
Above code works fine even though greet function is called before it's even declared. In JavaScript the entire function is hoisted to the top.

Thank you for reading this article. I hope that now you have clear understanding of JavaScript hoisting. Feel free to correct me if i have made any mistakes.