JavaScript Hoisting: What It Is And Why It Was Implemented
Tags: javascript, hoisting
Published: 2023-05-24 13:08:27


Hoisting is a key concept in JavaScript that can cause unexpected behavior in your code if you're not aware of how it works.

> _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. - MDN_

## Hoisting Variables

1. If you declare a variable after its first usage, this variable declaration is "hoisted" to the top of its scope.
2. If you assign a value to the variable, then the order it is assigned is unchanged and is unaffected by the hoisting.

See the following simple example.

```
function myFunction() {
  console.log(myHoistedVariable); // undefined for ES5 and below
  var myHoistedVariable= 1;
  console.log(myHoistedVariable); // 1
}
```

1. Since the declaration of `myHoistedVariable` is hoisted, the first `console.log` will attempt to print out the value (Note. the actual result will differ depending on if you use `var`, let or const)

2. The `console.log` will print undefined as the assignment of the value 1 isn't moved along with the hoisting (Note. this is for ES5 only using `var`).

The above example, basically is the same as the following code:

```
function myFunction() {
  var myHoistedVariable
  console.log(myHoistedVariable); // undefined for ES5 and below or ReferenceError for ES6 `let` or `const`
  myHoistedVariable = 1;
  console.log(myHoistedVariable); // 1
}
```
**Note. ES5 v ES6**
While hoisting technically still occurs with ES6, in practical effects you will be prevented from using it.

- ES5: If you are using var a hoisted value will return undefined . This behaviour is called Type 2 hoisting behaviour by MDN.
- ES6: For let and const declarations are also hoisted to the top of their scope, but they are not initialized with a value of undefined. 

Practically, this means you cannot use a let or const variable before it's declared, or you will get a ReferenceError. This is called Type 3 hoisting behaviour by MDN.

_If you declare a JavaScript file with 'use strict'; this will mean that hoisting using var will throw a Type 3 ReferenceError. (See [this article from Digital Ocean](https://www.digitalocean.com/community/tutorials/understanding-hoisting-in-javascript) for more info)_

## Hoisting Functions
Hoisting for functions get a bit more interesting:

- Function declarations are hoisted to the top of their scope. This means that you can call functions before they are declared.

```
myHoistedFunction();

function myHoistedFunction() {
    console.log("Hi I'm hoisted!");
}
```

- Function expressions are not hoisted. This means that if you declare a function expression using const or let you cannot call the function before this declaration. This is also the case for arrow functions as they are also function expressions.

## Why hoist at all??? 🤔
If this all seems pretty random and unnecessary, it did to me too - especially hoisting variables.

Why wouldn't you just enforce everyone to declare variables, functions and classes at the top of their scope? Even though this is largely corrected in ES6 and the move towards function expressions as the conventional norm (another hot topic for another day).

### Historical reasons
Digging into this a bit further I found this tweet from the archives:

<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/aravind030792?ref_src=twsrc%5Etfw">@aravind030792</a> var hoisting was thus unintended consequence of function hoisting, no block scope, JS as a 1995 rush job. ES6 &#39;let&#39; may help.</p>&mdash; BrendanEich (@BrendanEich) <a href="https://twitter.com/BrendanEich/status/522395336615428097?ref_src=twsrc%5Etfw">October 15, 2014</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

This [article on Quora](https://www.quora.com/Why-does-JavaScript-hoist-variables) explains this further. **TL;DR **Brendan Eich when implementing JavaScript (AKA LiveScript) in 10 days wanted to avoid the painful top to bottom enforcement of function declarations in ML languages like Lisp.

Brendan also followed up with a following tweet clarifying that var hoisting was unintended:

<blockquote class="twitter-tweet"><p lang="en" dir="ltr"><a href="https://twitter.com/aravind030792?ref_src=twsrc%5Etfw">@aravind030792</a> var hoisting was thus unintended consequence of function hoisting, no block scope, JS as a 1995 rush job. ES6 &#39;let&#39; may help.</p>&mdash; BrendanEich (@BrendanEich) <a href="https://twitter.com/BrendanEich/status/522395336615428097?ref_src=twsrc%5Etfw">October 15, 2014</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

From this context - the feature does make sense.

### Interpreter performance reasons
When the JavaScript engine compiles code, it first goes through a process called parsing, where it breaks down code into smaller, more manageable pieces.

By moving function declarations to the top of their scope before execution, the interpreter can avoid the need to search for the declaration of the function each time it is called. Instead, it can simply execute the function directly from memory, which can be faster and more efficient.

To summarise, it appears there are two key benefits of Hoisting:

1. **Allow you to use function declarations before they are defined**. This allows you to organise where you put your function code regardless of where they are called as long as they are within the same scope.

2. **Improve the performance of the interpreter**. Because variable declarations are moved to the top of their scope during compilation this may reduce the time the JavaScript engine needs to parse the code.

Some great resources on Hoisting/reading material related to the topic:
- [MDN docs on Hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting)
- [What is JavaScript Hoisting?](https://blog.bitsrc.io/what-is-javascript-hoisting-f0678208eb08#:~:text=Hoisting%20is%20JS's%20default%20behavior,only%20hoists%20declarations%2C%20not%20initializations.)
- [Stackoverflow discussion on hoisting](https://stackoverflow.com/questions/15005098/why-does-javascript-hoist-variables/15014769#15014769)
- [Quora: Why does JavaScript hoist variables?](https://www.quora.com/Why-does-JavaScript-hoist-variables)
- [A brief JavaScript history](https://launchschool.com/books/javascript/read/introduction)