views:

49

answers:

1
var foo = 'hello';

var myfunc = function() {
  console.log(foo);
  var foo = foo || 'world';
  console.log(foo);
}

myfunc();

why is the first foo logged to be 'undefined' ?

+8  A: 

Because on which line you actually declare a variable using "var" is irrelevant, as long as it remains in the same function. If a function has a var x declared anywhere within it, then any reference to that name is considered local to the scope where it is declared.

Of course, normally you don't reference a variable before it's declared, but consider this snippet:

function foo(a) {
   if (a) {
     var b = "something";
   }
   console.log(b);
}

Variable b is local to that function, hence whatever the value of a, usage of b won't accidentally refer to a variable declared on an enclosing scope.

Note: javascript only has function level scoping, it has no block level scoping.

RichN
+1, exactly right. More: http://blog.niftysnippets.org/2008/03/poor-misunderstood-var.html
T.J. Crowder
Why would you ever do what you've done in the snippet you just added? Introduces maintenance issues for no real benefit.
T.J. Crowder
@RichN: No, the compiler sees a `var foo` statement and compiles foo to be a local variable. Then when the code is interpreted, foo isn't yet defined to have any value. Hence it's value is 'undefined'. Remember, there are two phases: compilation and execution. All variable and function declaration are processed during compilation. But assignment must happen during execution because you need to evaluate expressions to get the correct value.
slebetman
@slebetman: Rich was responding to a comment by Delan that he's now deleted.
T.J. Crowder
@letronje: Just to be crystal-clear here, the correct output is "undefined" followed by "world". The unusual thing about `var` is that if you have `var x = 42;` in the middle of your function, it's *exactly* as though you had `var x;` at the top of your function and `x = 42;` in the middle. So here you're creating a variable `foo`, which shadows (supercedes) the one defined outside the function, and like all variables starts out with the value `undefined`. Later you assign a value to it which is effectively `foo = undefined || "world";` which evaluates, of course, to "world".
T.J. Crowder