0

Possible Duplicate:
variable hoisting

    var a = "global";

    //version 1
    function changeGlobal(){
        alert(a); //why is 'a' undefined here?
        if(a){ 
        var a = "local";
        alert(a);
        }
    }
    //version 2
    function changeGlobal(){
        alert(a); //why is 'a' 'global' here? what diff does 'var a="local"' make?
        if(a){ 
        //var a = "local";
        alert(a);
        }
    }
    changeGlobal();

Question are inline. Help me understand variable scoping.

Community
  • 1
  • 1
Antony Thomas
  • 3,576
  • 2
  • 34
  • 40
  • 1
    It's not a duplicate of that question, "variable hoisting", which states "global scope" and exhibits implementation anomalies, although it's related. –  Nov 17 '12 at 03:27
  • @jAndy There were tons of JS questions and I tried looking at couple before asking this. Also, I was reading the book 'javascript' by 'Alexei White', and he never talked about hoisting. – Antony Thomas Nov 17 '12 at 03:43
  • Why do your functions have the same name, and why is `var a = 'local'` commented out in the latter? How are we supposed to figure out which functions are called an in which order the variables get set? – Matti Lyra Nov 17 '12 at 15:43

3 Answers3

4

In javascript, variable declarations are 'hoisted' to the top of the function, independant of where you declared them.

So in the first variation of changeGlobal, when you declared var a = "local", the a variable declaration is hoisted up to the top. The assignment of the variable doesn't get hoisted as well, so at the point when you alert a, its an unassigned variable, hence undefined.

That is,

function changeGlobal(){
    alert(a); //why is 'a' undefined here?
    if(a){ 
    var a = "local";
    alert(a);
    }
}

is equivalent to

function changeGlobal(){
    var a;    // hoisted here (not assigned a value yet)
    alert(a); //why is 'a' undefined here?
    if(a){ 
    a = "local"; // only assigned a value here
    alert(a);
    }
}
Clark Pan
  • 6,027
  • 1
  • 22
  • 18
2

In version 1 you declare a local variable named a that takes precedence over the global a within the changeGlobal function. Even though it's defined after the alert(a); call, its definition is 'hoisted' up to the beginning of the scope, but isn't initialized until the var a = "local"; line. That's why the alert(a); shows undefined.

In version 2, because there isn't a local a, you're always dealing with the global a which is already initialized before the function runs.

JohnnyHK
  • 305,182
  • 66
  • 621
  • 471
1

JavaScript has lexical scoping, where a variable can be dereferenced from the program/function where it was vared, and down (as in, referencing it will not throw a ReferenceError.
The var statements will also be hoisted, and the initial value set to undefined.

Or in layman terms, variables are scoped to the function they are defined in, and all variables are available at any point during the functions execution although a value might not be assigned yet.

Combined, this is what you are observing - a local var shadowing the global var.

Sean Kinsey
  • 37,689
  • 7
  • 52
  • 71
  • I would say "function scoping" (as ECMAScript does not have block scoping, which is often associated with lexical scopes) and omit the usage of "dereferenced" (what does this even mean!?!). The term ReferenceError results from the fact that variables/property syntax constructs are internally decomposed into "references" (per the specification), but shouldn't be confused with "needing to be de-referenced for usage". –  Nov 17 '12 at 04:14