Hoisting is the behavior of moving declarations to the top of the current scope. This is the default behavior in JavaScript when using the var keyword but using the new let and const keywords means this does not occur.
Hoisting in Action.
Here we can see that the variable is declared after it’s been used, so how does this still work?
See the Pen
Hoisting in action by Chris Bertrand 💻 (@designpuddle-the-styleful)
on CodePen.
How and Why?
Why does JavaScript do this? Hoisting is done during the interpreter’s first run through the code. The JavaScript engine was designed in such a way that your code is run twice, the first time it runs through some syntax checking and anything that uses the global object methods. It then does some optimisation to improve performance, which is where hoisting comes in. The second pass is where your code gets run.
Initializations are Not Hoisted.
In this example, you can see that when declaring and initialising a variable in the same line the javascript engine does not optimise this block. As such you get an undefined error when trying to access the variable.
See the Pen
Hoisting Failure - Initialisation by Chris Bertrand 💻 (@designpuddle-the-styleful)
on CodePen.
Let and Const behave differently
See the Pen
Hoisting with Let and Const by Chris Bertrand 💻 (@designpuddle-the-styleful)
on CodePen.
When changing the first example to use the let or const keywords instead of var everything goes belly up. If you open your console window you will spot the JavaScript engine throwing exceptions (I’ve added images if you can’t be bothered 😉 )
You can see nothing is present in the results pane, that’s because these new keywords behave differently. The errors below are easy enough to understand, a const needs to be initialised when declared, whereas a let gets checked during the first cycle of the interpreter.
Put your declarations in scope.
Hoisting is pretty cool eh? It’s great that JavaScript is so forgiving and allows things like this to work. Equally, it can mean that code works when you’re not expecting it to. Going forward, it’s probably best to keep all your declarations at the beginning of every scope though! With the introduction and mass adoption of the let and const keywords, it’s important to know the differences, and know that simply changing all your vars to lets can cause problems in your application.
What about Functions
Hoisting also applies to function declarations, which is why you can define your function after you call them! However, Function expressions/Anonymous methods do not get hoisted in a similar fashion to let and const. Take a look at this last CodePen, we can see that the variable declarations get hoisted from the bottom, but the anonymous function call does not, which kills the engine throwing errors.
See the Pen
Hoisting - Functions by Chris Bertrand 💻 (@designpuddle-the-styleful)
on CodePen.
Finally, it’s good to know that functions get hoisted before variables! So when refactoring legacy code, remember to look at the scope of all your variables and think about how the interpreter will be parsing the code you are modifying.
Resources
https://www.w3schools.com/js/js_hoisting.asp
https://en.wikipedia.org/wiki/JavaScript_engine
https://www.codingame.com/playgrounds/7974/understanding-hoisting-in-javascript
https://codeburst.io/javascript-what-is-hoisting-dfa84512dd28