Question

I’ve run into a very strange (to me) problem with the var keyword. I’ve reduced it to a fairly minimal test case, and found it’s exhibited in Node.js (thus, V8 and Chrome), Safari 4’s inspector (thus, Nitro), and FireBug (obviously, SpiderMonkey). I was originally preparing a bug report, but since it’s so widely displayed, I’m going to assume that I completely misunderstand how JavaScript is supposed to scope and look up variables.

The test case is very small, and on GitHub here: http://gist.github.com/260067. The only difference between the first and second example is the inclusion of the var keyword.

Here, as well, is a similar test case that exhibits the same ‘problem’ in a different way: https://gist.github.com/698b977ee0de2f0ee54a

Edit: To preclude any more answers attempting to explain how cascading scope works, I’m intimately familiar with that. My problem, is that I don’t understand why the following code ‘works’ (in that it alert()s ‘outer,’ followed by ‘inner,’ and then again ‘outer’):

(function(){
  var foo = 'outer';
  alert("Outer `foo`: " + foo);

  (function(){
    foo = 'inner';
    alert("Inner `foo`: " + foo);

    var foo;
  })();

  alert("Outer `foo`: " + foo);
})();

The var foo; occurs in a completely irrelevant position to the re‐assignment of foo; so why does it affect that assignment in a very substantial way?

Was it helpful?

Solution

The thing is that unlike other languages, JavaScript creates all variables at the start of a function. This means that the code:

(function(){
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        var myVar = 5;
    }
})();

Is actually compiled and interpreted as

(function(){
    var myVar;
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        myVar = 5;
    }
})();

To create a variable and only have it available inside an if or loop block, you have to use let, which is a new JavaScript feature. I'm not sure how many browsers implement it yet (Firefox 3.5 does if you use <script type="text/javascript;version=1.7">).

(function(){
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        let myVar = 5;
    }
})();

OTHER TIPS

var exports doesn't work exactly like local variables in many languages. It declares exports as local variable in the whole function instead of just the enclosing block (even though it appears after the first usage), so the function argument with the same name is hidden.

Edit: the let keyword works more conventionally (it declares a variable only for the containing block) but it isn't available in all versions of JavaScript.

the inclusion of var means that the assignment of the {} is done to a local variable exports instead of the global variable exports, which means it has no effect.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top