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 declerations 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 declerations
  • Variables hoisted
  • No decleration for fellowship because it was a already named/declared function so it will just be overwritten/re-assigned.

Due to the reasons how javascript hoisting works, we should always declare variables at the top of its scope to prevent getting unexpected results and in addition to that always use "use strict;" on all our scripts (.js) to enforce more checks.

This was my learning when I went through CodeSchool Javascript course followed by some additional reading online.