Hoisting in JavaScript

In order to test my understanding of hoisting, closure and scope in JavaScript, I put together a number of exercises (with the help of my colleague Kevin). Each successive exercise builds on the last and the output of the function can be viewed by hovering or clicking the text in the output section below the respective exercise.

What is the output?

(function () {
    var test = 5;

    if (false) {
        test = 7;
    } else {
        console.log(test + 2);
    }
}());
hover for result

7

What is the output?

(function () {
    var test = 5;

    if (false) {
        var test = 7;
    } else {
        console.log(test + 2);
    }
}());
hover for result

7

What is the output? Is test global?

(function () {
    test = 5;

    if (false) {
        var test;
    } else {
        console.log(test + 2);
    }
}());
hover for result

7

What is the output? Is test global?

(function () {
    test = 5;

    if (false) {
        //var test;
    } else {
        console.log(test + 2);
    }
}());
hover for result

7

What is the output? Will it error and break? Is test defined?

(function () {
    if (false) {
        var test = 3;
    } else {
        console.log(test + 2);
    }
}());
hover for result

NaN

What is the output? Is one defined? Will it error? Or is it one of these digits: 3, 4, 5, or 6?

(function () {
    test = 5;

    if (false) {
        var test = 3;
    } else {
        console.log(one(test));
    }

    function one(value) {
        return value + 1;
    }
}());
hover for result

6

What is the output? Is one defined?

(function () {
    test = 5;

    if (false) {
        var test = 3;
    } else {
        console.log(one(test));
    }

    var one = function (value) {
        return value + 1;
    };
}());
hover for result

TypeError: undefined is not a function

Is the function one hoisted to the top of the highest scope? Is one a function or an integer? What is one where? ;)

(function () {
    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        }(test));

    console.log(one);
}());
hover for result

1

Is one hoisted to the top of the highest scope?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));
}());
hover for result

TypeError: undefined is not a function

What are the values of one? What is the output? Does recursion still apply? Which one declarations have precedence where?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    function one(value) {
        return value;
    }
}());
hover for result

3,1

Is one still hoisted to the top even though it’s immediately executed? Does it behave the same as before?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    function one(value) {
        return value;
    }(4);
}());
hover for result

3,1

Is one hoisted to the top now that it’s enclosed by parenthesis?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    (function one(value) {
        return value;
    }(4));
}());
hover for result

TypeError: undefined is not a function

Is one hoisted to the top even though it’s immediately executed and assigned with a name?

(function () {
    console.log(one(3));

    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    var identity = function one(value) {
        return value;
    }(4);
}());
hover for result

TypeError: undefined is not a function

What’s the output?

(function () {
    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    var identity = function one(value) {
        return value;
    }(4);
    console.log(identity);
}());
hover for result

1,4

What’s the output?

(function () {
    var test = 5,
        one = (function one(value) {
            if (value > 2) {
                return one(value - 1);
            }
            return value - 1;
        });

    console.log(one(test));

    var identity = function one(value) {
        return value;
    }(4);
    console.log(identity(3));
}());
hover for result

TypeError: number is not a function

Lessons Learned

  • When var is not used, variables are made global
  • Variable names take precedence over function names (in the case of duplicates)
  • Variable declarations (e.g. var myObj) are hoisted to the top of function scope; however, assignment is NOT hoisted
  • Function declarations (e.g. function myFunc() { }) are hoisted to the top of function scope
  • Function expressions (e.g. var myFunc = function someFunc() { }) are NOT hoisted to the top of function scope
    • They are treated like variable declarations–the variable definition is hoisted, but the assignment is not hoisted
    • someFunc cannot be called outside of its assignment; someFunc is undefined (ReferenceError); must use myFunc
  • Immediately executing function declarations has no effect on hoisting–the function will still be hoisted to the top of function scope

More JavaScript

4 Comments

  1. The error in the last output is incorrect. It should be identity and not number.

    Reply

Comments, questions and feedback welcome.