4

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.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
Futur
  • 8,444
  • 5
  • 28
  • 34

1 Answers1

3

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.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Thank you very much for the answer. now i understood. but i also have another clarification:(from the link you gave from MDN) var x = 0; function f(){ var x = y = 1; // x is declared locally. y is not! } f(); console.log(x, y); // 0, 1 ==> why 'y' leaked in here ? – Futur Jun 16 '13 at 19:04
  • 1
    @Futur `var` doesn't affect variables used after a `=`, so `var x = y = 1;` is actually `y = 1; var x = y;` and `y` is set without a declaration, which can result in it [becoming a global](http://stackoverflow.com/q/1470488/). To declare and set both `x` and `y`, they should be comma-separated -- `var x, y; x = y = 1;` or `var x = 1, y = x;` – Jonathan Lonowski Jun 16 '13 at 19:23