🔥🕺🏼 JavaScript Visualized: Hoisting
Tags: javascript
Published: 2019-11-20 07:12:16

Hoisting is one of those terms that every JS dev has heard of because you googled your annoying error and ended up on StackOverflow, where this person told you that this error was caused because of _hoisting_ 🙃 So, what is hoisting? (FYI - _scope_ will be covered in another post, I like to keep posts small and focused)


If you’re new to JavaScript, you may have experienced “weird” behavior where some variables are randomly `undefined`, `ReferenceError`s get thrown, and so on. Hoisting is often explained as _putting variables and functions to the top of the file_ but nah, that’s not what’s happening, although the behavior might seem like it 😃

When the JS engine gets our script, the first thing it does is **setting up memory** for the data in our code. No code is executed at this point, it’s simply just preparing everything for execution. The way that function declarations and variables are stored is different. Functions are stored with a **reference to the entire function**.

<img src="https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif7.gif" />

With variables, it’s a bit different. ES6 introduced two new keywords to declare variables: `let` and `const`. Variables declared with the `let` or `const` keyword are stored _uninitialized_.

<img src="https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif8.gif" />

Variables declared with the `var` keyword are stored with the default value of `undefined`. 

<img src="https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif9.gif" />

Now that the creation phase is done, we can actually execute the code. Let's see what happens if we had 3 console.log statements on top of the file, before we declared the function or any of the variables.

Since functions are stored with a reference to the entire function code,  we can invoke them even _before_ the line on which we created them! 🔥

<img src="https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif16.gif" />

When we reference a variable declared with the `var` keyword before their declaration, it’ll simply return its default value that it was stored with: `undefined`! However, this could sometimes lead to "unexpected" behavior. In most cases this means you’re referencing it unintentionally (you probably don’t want it to actually have the value of `undefined`) 😬

<img src="https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif17.gif" />

In order to prevent being able to accidentally reference an `undefined` variable, like we could with the `var` keyword, a `ReferenceError` gets thrown whenever we try to access _uninitialized_ variables. The "zone" before their actual declaration, is called the **temporal dead zone**: you cannot reference the variables (this includes ES6 classes as well!) before their initialization.


<img src="https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif18.gif" />

When the engine passes the line on which we actually declared the variables, the values in memory are overwritten with the values we actually declared them with.


(Oops I notice now this should be number 7. Will update asap 😬)
<img src="https://devtolydiahallie.s3-us-west-1.amazonaws.com/gif12.gif" />

---

All done! 🎉 Quick recap:

- Functions and variables are stored in memory for an execution context before we execute our code. This is called _hoisting_. 
- Functions are stored with a reference to the entire functions, variables with the `var` keyword with the value of `undefined`, and variables with the `let` and `const` keyword are stored _uninitialized_. 

I hope that the term _hoisting_ is a bit less vague now that we've looked at what's happening when we execute our code. As always, don't worry if it still doesn't make a lot of sense yet. You'll get a lot more comfortable with it the more you work with it. Feel free to ask me for help, I'd love to help you! 😃