Hoisting in Javascript

Hoisting in Javascript

A rather unknown topic of Javascript is Hoisting. The Javascript compiler does not execute code as we write it. Hoisting is its way of re-arranging our code before executing it which is making declarations and taking it to the top of current scope. So, below code snippet:

function SumSquare(a, b) {
    var x = add(a * a, b * b);
    return x;

    function add(c, d) {
        var a = c + d;
        return a;
    }
}

Interpreted as:

function SumSquare(a, b) {
    var x = undefined;

    function add(c, d) {
        var a = c + d;
        return a;
    }

    x = add(a * a, b * b);
    return x;
}

As we can see, JS did the following:

  • Declared variables
  • Hoisted declerations to the top of current scope
  • Hoisted declared/named functions to the top

But same cannot be said for function assignments :

function Random() {
    var random = function(){
        return 10;
    };

    return random;

    var random = function (){
        return 9;
    };
}

Will become:

function Random() {
    var random = undefined; //will be overwritten by 2nd random
    var random = undefined;

    var random = function(){
        return 10;
    };

    return random;

    //unreachable
    var random = function (){
        return 9;
    };
}

This is what happened:

  • Function assignments did not get hoisted because assignments are not hoisted
  • Variables with same identifier gets overwritten by the last one
  • Second random function will not be reached because of return

Lets go through another complex one for fun:

function theBridgeOfHoistingDoom() {
    function fellowship() {
        return "friends";
    }
    var sword = "sting";
    var dwarf = function () {
        return "axe";
    };
    var fall = "Fly you fools!";
    fellowship = function () {
        return "broken";
    };
    ring();
    return sword;
    fellowship = function () {
        return "mines"
    };
    sword = function () {
        return "glamdring";
    };
    var ring = function () {
        return "precious";
    };
}

Will become:

function theBridgeOfHoistingDoom() {
    var sword = undefined;
    var dwarf = undefined;
    var fall = undefined;
    var ring = undefined;

    function fellowship(){
        return "friends";
    }
    sword = "sting";
    dwarf = function () {
        return "axe";
    };
    fall = "Fly you fools!";
    fellowship = function () {
        return "broken";
    };

    ring();
    return sword;

    //unreachable
    fellowship = function () {
        return "mines"
    };
    sword = function () {
        return "glamdring";
    };
    ring = function () {
        return "precious";
    };
}

Things happened above:

  • Variable declarations
  • Variables hoisted
  • No declaration for fellowship because it was already named/declared function so it will just be overwritten/re-assigned.

At the time when I wrote this post back in 2015, ES6 was not around. But now in 2021, hoisting of var is a thing of the past with addition of let and const in JS. Unlike var which is function-scoped, let and const are block-scoped. They will be hoisted to the top of their immediate scope but unlike var they won't be initialized with undefined therefore, there will be a ReferenceError instead of just outputting undefined which is much more type-safe and predictable. Always prefer to use const if not, then let.