~ 2 min read

Hoisting in JavaScript


TL;DR

All declarations (var, let, const, function, function*, class) are hoisted in JavaScript. The difference between var/function/function* declarations and let/const/class declarations is the initialisation.

First, let’s understand the definition of hoisting in JavaScript:

Let’s call the var/function/function* group as group 1, and the remaining group as group 2. When the JS engine reads through the JS code, it will find all bindings in the code and declare those bindings. However, for group 1, they are initialised immediately when the binding is created with the value undefined, while group 2 remains in an uninitialised state. After the JS engine executes the declaration line of that binding (where the let/const/class statement is written), then that binding is initialised - meaning if you try to access that binding before it is initialised, a ReferenceError will occur.

var x = "global",
    y = "global";
(function() {
    x; // undefined - this is normal hoisting in JS
    y; // Reference error: y is not defined - y is still hoisted to the top of the function scope
       // But instead of receiving the value undefined, the JS engine will throw an error if we try
       // to access variable y before the JS engine executes the let y = ... statement on line 12

    // some code here...

    var x = "local";
    let y = "local";
}());

Sources and References:


Headshot of Nam Le

Hi, I'm Nam Le. I'm a software engineer based in HCM city, Vietnam. You can follow me on Twitter, see some of my work on GitHub, or connect with me on LinkedIn.