[JAVASCRIPT](https://www.kirupa.com/html5/learn_javascript.htm)
[BOOK](https://www.amazon.com/exec/obidos/ASIN/0789758067/kirupacom)
# Variable Hoisting
by [ kirupa](https://www.kirupa.com/me/index.htm) | 30 May 2017
One of the quirkiest things about JavaScript is this thing known as ** hoisting**. We'll get to what it means in a bit, but let's set the stage for it by looking at some examples and figuring out what the right behavior should be. For our first example, take a look at the following code:
```js
function foo() {
return "Yay!";
}
console.log(foo());
```
What do you think is going to be displayed in our console when this code runs? Here are three choices:
1. undefined
1. Error - foo isn't referenced
1. Yay!
If you guessed **Yay!**, you would be right. There wasn't anything tricky there, so that was pretty straightforward. Let's kick things up a notch and take a look at a slightly modified version of our earlier code:
```js
console.log(foo());
function foo() {
return "Yay!";
}
```
What do you think is going to be displayed in the console now? Will it be the same as before? Will it be something different?!! As it turns out, the answer is the **same as before**. Our console will print out **Yay!** as the output. Hmm...
It's time for our last example. Take a look at the following code:
```js
console.log(bar);
var bar = 100;
```
This seems similar to what we've seen so far, right? You would expect the value **100** to be printed to the console. The actual answer is a whopping **undefined**. What is going on here? By the end of this article, you will know all about it.
Onwards!
## JavaScript and Compiler Optimizations
When you are running JavaScript, you have a JavaScript engine that takes the code you write and turns (aka ***compiles***) it into the stuff that your computer understands and knows what to do with. As part of turning your code into something your computer understands, the ***compiler*** (aka the thing that does the turning) performs a variety of optimizations. One of these optimizations has to do with what happens when our compiler runs into any variable and function declarations. Depending on whether the declaration is for a variable or a function, the optimization is a little different. Let's look at each case separately.
### Variable Declarations
Whenever our compiler encounters a block of JavaScript, the first thing it does is scan the entire block for any variable or function declarations. Take a look at the following example we saw earlier:
```js
console.log(bar);
var bar = 100;
```
Our compiles looks at both of these lines, but before anything gets executed, it hones in on the variable declaration where we declare the `bar` variable. At this point, what it does is promote the variable declaration to the beginning of the code it is looking at. From the compiler's point of view, our code will look a bit like this:
```js
var bar;
console.log(bar);
bar = 100;
```
This promotion of the declared variable is known as **variable hoisting**. The important thing to note is that only the declaration is hoisted. The initialization where we set the `bar`'s value to **100** remains in the exact same spot. Anyway, getting back to our example, what we are printing to the console is a variable that is clearly defined even though you specified it AFTER your `console.log` call. This works because of hoisting, but what gets printed is **undefined**. The reason is that the variable hasn't been initialized at this point in time.
### Function Declarations
The behavior you saw with variable declarations is similar for functions as well. The major difference is that the entire function is hoisted - not an empty shell of it. Let's revisit our earlier example:
```js
console.log(foo());
function foo() {
return "Yay!";
}
```
When our compiler scans this block of code, it hoists the `foo` function to the top. What you have is something that ends up looking as follows:
```js
function foo() {
return "Yay!";
}
console.log(foo());
```
That is why the output for this example is **Yay!**. Pretty simple, right?
### Some Hoisting Quirks
We are almost done here. Just because we understand how hoisting works doesn't mean there aren't some exceptions to what we've seen. First, hoisting doesn't apply to function expressions. Look at the following example:
```js
console.log(foo());
var foo = function() {
return "Yay!";
}
```
The output isn't going to be **Yay!** like we saw with plain old functions earlier. It is going to be a **TypeError: foo is not a function**. The other time you will encounter hoisting inconsistencies is when you are creating classes using the `class` keyword:
```js
var foo = new AwesomeSauce();
class AwesomeSauce {
constructor() {
console.log("I exist!");
}
}
```
When this code executes, you wll get a **ReferenceError** when initiailizing the `foo` variable. Your class definition needs to appear before attempting to actually use the class. This applies to class expressions as well. No hoisting for them either.
## Conclusion
For the longest time, we've always been told to declare our variables and functions first before initializing them. We've also been told to only ***use*** a variable or function after it has been initialized. None of that guidance changes. Just because JavaScript has an optimization around hoisting declarations to the top of the current scope doesn't mean we should make our code more difficult to read by relying on it.