-2

Maybe it's stupid, but I really feel depressed by the 'var' keyword. I have trouble in figuring out the following problems:

var local = true;
function outer() {
    /* local scope */
    var local = false;
    function inner() {
      alert(local);
      var local;
    }
    inner();
}
outer();

function a(x) {
    return x * 2;
}
var a;
alert(a);

Any explanations are appreciated.

  • Have a look at that post: http://stackoverflow.com/questions/1470488/difference-between-using-var-and-not-using-var-in-javascript – edi9999 Jul 15 '13 at 06:42
  • 2
    This seems like a job for google: [`"mdn javascript var keyword"`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/var) – jahroy Jul 15 '13 at 06:44
  • You have nested functions in the example. Scope of variables defines where they can be seen or used and works at function level in Javascript, not at code block or code line level as in other languages. see http://stackoverflow.com/questions/111102/how-do-javascript-closures-work – Paul Jul 15 '13 at 06:47
  • 1
    The odd behaviour is due to javascript hoisting. Google and read about it. – Chandermani Jul 15 '13 at 06:48
  • why you don't feel depressed by keyword 'function', anything special? – Sudarshan Tanwar Jul 15 '13 at 07:37

1 Answers1

2

Annotated source; I'm assuming this code starts out at global scope:

var local = true;      // Creates a global variable called `local`
function outer() {
    /* local scope */
    var local = false; // Creates a local `local` within `outer`, shadowing (hiding) the global
    function inner() {
      alert(local);    // alerts "undefined", the value of `inner`'s `local`
      var local;       // Creates a local `local` within `inner`, shadowing (hiding) `outer`'s version
    }
    inner();
}
outer();

function a(x) {        // Creates a global function `a`
    return x * 2;
}
var a;                 // Has no effect
alert(a);              // alerts the function source (on engines that have it)

There are basically three things at work in the code above:

  1. A declaration in a nested scope shadows (hides) a declaration in a containing scope. So the local in outer shadows the global, and the local in inner shadows outer's local.

  2. var declarations are processed when execution enters an execution context, not where they appear in the source code. They're sometimes said to be "hoisted" because they are effectively moved up (raised, hoisted) to the top of the context in which they occur. (More: Poor misunderstood var) This effect is particularly noticeable within the inner function, because the local being alerted is the one from inner, not the one from outer (which is why it's undefined), even though the declaration is underneath the alert.

  3. Function declarations create a symbol in the scope in which they're defined, in the same symbol space as var declarations do. (Specifically, they both create entries in the binding object of the lexical environment of the execution context in which they occur.) So if you have a function declaration and a var with the same name (as you do with a at the end of your code), there's a conflict. Which wins? The function declaration wins, because of the order dictated by §10.5 of the specification, which says that function declarations occur before var declarations, and that a var for a symbol that's already defined doesn't override it.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875