Hoisting in JavaScript: A Step-By-Step Explanation

Alina Kornilova
The Startup
Published in
7 min readJul 28, 2020

To understand what hoisting in JavaScript is, let us first refer to a definition of this word:
“Hoist — raise (something) using ropes and pulleys” (Merriam-Webster Dictionary)
This term is often used in terms of raising a flag, for example:
Pirates hoisted a black flag approaching their enemy's land as a signal they are going to attack.

Therefore, hoisting as a noun can be defined as an act of raising something. While hoisting in JavaScript gives its hoisting much more amicable meaning than pirates, its intention is still the same — to declare an act before its execution.

Variable Hoisting
Var
In programming, we use variables. Variable is a value that can change, depending on conditions or on information passed to the program. Let take an example using the analogy with pirates.
Imagine, we decided to build a Pirates Attack game app. There are two players-one plays for pirates, and another one — for defendants. We approached the part in our code, where we need to make sure pirates have their flags on the ship when they are leaving their land to enemies’ land to raise it. We do not know yet what color of the flag pirates will raise (it depends on the second player’s actions). While approaching the enemy’s land, the captain may look at the binocular and sees that the land is full of gold, then he will give an order to raise a black flag. Otherwise, he might look at the land and see that his old buddy from elementary school is living there, and he does not want to attack him, then he will give an order to raise a white flag. All we care for now is that pirates ship need a flag variable in our app sometimes in the future, and we can determine the value later.

In JavaScript language, this act is called *variable declaration*. We declared a variable, but we have not assigned it yet.

Let come back to our pirates. The captain has looked into the binocular and saw lots of gold on enemies’ land. He decides to invade the enemy. He gives to raise a black flag on the ship; in other words, he assigns to raise a black flag. As a programmer, you need to assign a var flag to be a black one.

The next thing to do is to raise this black flag on the ship. Now you need to have a method called raiseFlag() where you will pass `flag` as an argument.

Let us see the steps we took to use our variable:

1. We declared the variable `flag`
2. We assigned the value `black flag` to our variable
3. We executed the variable in our `raiseFlag()` function.

What would happen if we change the order of our commands? The captain told to bring a flag on the ship without specifying which one, and then, after looking in the binocular, he gives a command to raise a flag. What flag will the crew raise? Let us see.

Oops! `Flag` is `undefined`.

Now let us imagine that the captain is getting old and forgets to tell what flag to raise and tell the crew to bring the flag on the ship at all!

`Flag` is `undefined` again. However, we have not run into the error, trying to execute the undeclared variable. The code was still running; it just gives us an undesired result — the variable is undefined. It is what hoisting does! JavaScript has hoisted (invisibly to us, behind the scene) the variable declaration above the rest of the code. Due to hoisting, JavaScripts can identify the variable declaration first and runs the rest of the code. From JavaScript’s point of view, there is no difference between the last two snippets of code — it sees it as shown on the first snippet.
Due to this reason, we have to be careful and always declare and assign the variable simultaneously:

Let
The variables declared with `var` keyword are function scoped (we can see it throughout the entire function). Now let us examine what happens when we use block-scoped variables defined with `let` and `const` keywords.

If we try to call a `let `variable before we declared and initialized it, we do not get undefined anymore, but we see a `Reference Error: variable is not defined`. It means that we can no longer to execute our code before the variable is declared, and JavaScript can no longer initialize the variable behind the scene to run the following code.
Now, let us try to declare a variable before the execution code, and assign it after.

Woohoo! JavaScript will still run the code even if the variable was not assigned yet, and gives us `undefined`. However, such implementation will most likely cause an undesired outcome when you run the application. Again, we come to the importance of declaring and assigning variables before executing them.

Const
There is one more keyword that ES6 has event a stricter mode for — `const` . It is similar to `let` variable being a block-scoped, but it has its differences. Unlike `let` , `const` is an immutable variable, which means we cannot reassign it to a different value. If `let` allows to execute code when we at least declare the variable before the execution, `const` will not execute code unless a variable was both declared and assigned before execution.

Even if we have declared before execution, but no assigned, the result will be still the same (error):

ES6 still performs hoisting in all cases considered above: `var`, `let`, and `const`. It means that it is still scanning behind the scene to find the declared variable and raise it to the top or above the execution code. However, the difference is in initialization (or assignment) outcomes:
•`Var` is initialized with a value “undefined”;
•`Let` and const remains initialized (just declared).

Hoisting functions
We can divide all functions can into two types: Function Declaration and Function Expressions.

Function Declarations
Function declarations, similar to variable declarations, are hoisted. We can call a function before declaring it.

Function Expression
Function Expressions are not hoisted. Let us try:

Even if we try to declare a function and express it, JavaScript will only hoist the declaration, but not the assignment. Therefore, it will not see that variable as a function:

Precedence
Hoisting also has a specific hierarchy:

When hoisting, JavaScript will always make a priority to hoist variable assignment over function declaration and a function declaration over the variable declaration.

As we see, JavaScript applied the assignment to the “flag” given by its variable, not the function declaration. However, if we just declare a variable, then JS will prefer hoisting function declaration instead:

Classes
Classes, similar to functions, can be classified as declaration classes and expression classes.
Declaration class is hoisted, but remains uninitialized:

We get a Reference Error that the flag is not defined, which means that though variable declaration BlackFlag was hoisted, it stayed uninitialized because JS didn’t find what flag is. Yet, once we reverse the order and declare the class variable Flag first, JS can successfully identify the class Flag and use it.

Class expressions, same as function expressions, are not hoisted:

JS did hoist var Flag, but as a variable declaration (remember the hoisting priority of arable declaration over function declaration?), not as a function. Therefore, it did not hoist the variables assigned to a class.

Conclusion
To summarize all the above, let us bring all the information into a diagram:

--

--