Javascript: Scope of variables - Clarification request

Problem

I came across this piece of code from a friend and I'm wondering why is this working this way.

Assume two files: scope2.js and scope3.js

scope2.js

console.log(foo);
var foo=6;
woo=5;
(function()
{
    console.log(foo);
    console.log(woo);
    var foo=5;

console.log(foo);
console.log(woo);
})();

The output when executed in NodeJS env, >>> "node scope2.js"

undefined undefined 5 5 5

Now, Scope3.js

console.log(foo);
var foo=6;
woo=5;
(function()
{
    console.log(foo);
    console.log(woo);
    var foo=5;
    var woo=6;
    console.log(foo);
    console.log(woo);
})();

Output of the above code in nodejs env is :

undefined undefined undefined 5 6

Why this behavior ?

I understand most of the basics of variable scoping in JS, but this is confusing me, I dont want to understand something with some bad assumptions.

Problem courtesy of: Futur

Solution

The fact you miss is that variable declarations are "hoisted" to the start of their scope (which is either the function in which they're declared or the global scope).

So your second code is equivalent to

var foo;
console.log(foo); // undefined value
foo=6;
woo=5;
(function()
{
    var foo, woo; // shadow the external variables
    console.log(foo); // undefined value
    console.log(woo); // undefined value
    foo=5;
    woo=6;
    console.log(foo); // 5
    console.log(woo); // 6
})();

Those hoisted variable declaration shadow the external variable from the start of the function even if they get a value only after the two first console.log.

In the first code, the difference is that woo isn't declared in the inner scope, so you're logging the external value.

Solution courtesy of: Denys Séguret

Discussion

There is currently no discussion for this recipe.

This recipe can be found in it's original form on Stack Over Flow.