3

I have a Javascript main file that is enclosed by an immediately-called closure (so as not to pollute 'global':

(function () {
"use strict";
   var closureVariable = [];
...
}());

I made a simple, bone-headed coding error when removing a variable from a function header such that my code had a comma instead of a semicolon:

function fred () {
    var i,

    closureVariable = [1,2,3,4];
    confused();
}
function confused () {
    console.log(closureVariable);     // Prints '[]'
}

Certainly the missing semicolon on the 'var i' line was the problem. However the behavior I thought should happen is that my now locally-defined variable 'closureVariable' should have shadowed the higher-level scope definition, and the value of my locally-defined variable should have been available to functions lower down in the scope chain (that is, function 'confused' should have printed out '[1,2,3,4]';

What am I not understanding about Javascript scope chains here?

wolfstevent
  • 633
  • 8
  • 13

3 Answers3

3
var i,

    closureVariable = [1,2,3,4];

makes two new variables, available in the fred function and in functions defined in this scope.

Those variables are totally different from any variable defined outside the fred scope, even if they happen to have the same name.

Shadowing, here, means that your variable named "closureVariable" prevents any direct access to the variable having the same name in the outer scope.

Denys Séguret
  • 335,116
  • 73
  • 720
  • 697
3

What you are expecting is known as dynamic scoping. This is a valid language design choice, though widely considered inferior today. It's just not what Javascript does. Like many popular languages, Javascript uses lexical scoping. That means confused's scope is not considered a child scope of fred's, because its definition is not inside the definition of fred. The fact that fred calls confused has no effect.

1

When you redefined the closureVariable by omitting semicolon it was redefined only in the context of fred function. The confused function exist in the context of your closure, so it still sees the original closureVariable. If you had your confused function defined inside of the fred function it would see the new closureVariable and would print [1,2,3,4]

(function () {
  "use strict";
  var closureVariable = [];
  function fred () {
   var i,

   closureVariable = [1,2,3,4];

   function confused () {
      console.log(closureVariable);     
   }

   confused();  // print [1,2,3,4]
  }
 })();

Or if you want to call confused from outside of fred()

(function () {
  "use strict";
  var closureVariable = [];
  var confused;

  function fred () {
   var i,

   closureVariable = [1,2,3,4];

   confused = function () {
      console.log(closureVariable);     
   }  
  }

  confused();  // print [1,2,3,4]
 })();
Vlad
  • 8,407
  • 4
  • 39
  • 60