JavaScript hoisting
Tags: javascript, programming, beginners, webdev
Published: 2021-03-09 15:20:47

Consider the below simple code snippet:
```javascript 
console.log(i);  // undefined
var i = 0;
```
The above code on execution gives undefined as the answer. 
Now observe the snippet again, __*i*__ variable is called before it is initialized. In a normal case, it should give a Reference error (The variable cannot be called before initialization). 

But it does not in JavaScript. Why Is it so? If you are confused with the above snippet, then this blog is for you

## What is actually happening?
In the above code, __var__ keyword is pushed above the code and initialized automatically by JavaScript *(only __i__ variable is pushed above, not the value __0__)*. So at the time of execution of code, it becomes something like this:

```javascript
var i; // automatically inserted by JS Engine at run time
console.log(i);
var i = 0;
```
__*i*__ has been pushed above and initialized by the JS engine, that's why we get __undefined__ at the console line instead of an Error.

When we execute a code in JavaScript, the JS engine moves the variables & functions declarations to the top of the code. This feature or behavior of JavaScript is known as __*Hoisting*__ in JavaScript.

## What about let and const?
As written above, JS moves all the variables and functions at the top of the code, but in the case of var, it initializes it.
This is not the case with let & const. 
Consider the below code with let keyword-based variable declaration

```javascript
console.log(i);
let i = 0;
```
When the above code is executed, we get something like this:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p36pgh4x0ecb6r0b2sse.PNG)

So in the case of let and const keyword, the JS engine hoists the variable declarations but __doesn't initialize__ them. JS engine is aware of the variable, but it cant be used until it is declared or initialized. Hence the variable comes in the __*temporal dead zone*__ until it is declared and we get __Reference Error__.

##Hoisting a Function
As written above, __functions__ are also hoisted in JavaScript. 

Consider the below code:
```javascript
let x = 20,
    y = 30;
let total = add(x, y);
console.log(total);  // 50, because of hoisting
function add(a, b) {
  return a + b;
}
```
In the above code, the output will be 50 as the regular function is also hoisted (moves to the top of the script) in JS.

### What if it's a function expression?

Consider the below code:
```javascript
let x = 20,
    y = 30;
let total = sum(x, y);
console.log(total); // Error
var sum = function (a, b) {
  return a + b;
};
```
In the above code, we get the following output:
![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pvbefndabahjhvk234h3.PNG)
As the function is stored in the variable sum (declared by var keyword), it is __hoisted and initialized__ above (not the function expression, as only variable is pushed above, not the value), and the value of __*sum*__ gets undefined. Therefore we get sum is not a function as it is undefined.
At the time of execution, the code will be like this:
```javascript
let x = 20,
  y = 30;
var sum // Automatically inserted by JS engine
let total = sum(x, y);
console.log(total);
var sum = function (a, b) {
  return a + b;
};
```


#### Conclusion
* JavaScript hoisting occurs in every variable and a function
* In hoisting, the variable and functions are pushed above the script or the scope
* let and const are hoisted but not initialized, hence they remain in the Temporal dead zone until they are declared
* When it is let/const, one should always move the variables declarations to the top of the scope (to avoid temporal dead zone)
* Function expressions arent hoisted