Search code examples
javascriptscopeclosureslexical-closures

How does the JS scope of these blocks work?


Can anyone explain why the following produces 1,2 and the other produces 5? Should they not both produce 5?

//produces 1,2
(function () {

    var a = [5];

    function bar() {
        if (!a) {
          var a = [1, 2];
        }
        console.log(a.join());
    }

    bar();

})();

Based on reading some articles about JS closure, I expect them both to produce 5. Can't seem to find an article anywhere that would give some insight as to why the first block produces otherwise.

//produces 5
(function () {

    var a = [5];

    function bar() {
        if (a) {
          console.log(a.join());
        }
        else {
          console.log([1, 2].join())
        }
    }

    bar();

})();

Thanks!


Solution

  • Due to javascripts var hoisting, this code:

    (function () {
        var a = [5];
        function bar() {
            if (!a) {
              var a = [1, 2];
            }
            console.log(a.join());
        }
        bar();
    })();
    

    is equivalent to this code:

    (function () {
        var a = [5];
        function bar() {
            var a; // a === undefined at this point
            if (!a) {
              a = [1, 2];
            }
            console.log(a.join());
        }
        bar();
    })();
    

    So you can see, a will indeed be falsey (i.e. !a === true) when the if condition is tested