A: 

When you redeclared y with var y;, it's now undefined, so if(!undefined) evaluates to true.

Add another alert in your example to see this:

//create global variable with square bracket notation
window['y'] = 'old';

//redeclaration of the same variable
var y;
alert(y); //undefined

if (!y) y = 'new';

alert(y); // new

var won't initialize a variable twice, but it will overwrite one not initialized the first time (because it's a new, more local variable), which the window['y'] style does, adding it to the window object. Take this for example:

//create global variable with square bracket notation
window['y'] = 'old';

//redeclaration of the same variable
var y;
alert(y); //undefined

alert(window.y); //old

if (!y) y = 'new';

alert(y); //shows New instead of Old
alert(window.y);​ //still old
Nick Craver
If that was true why did the second snippet of code not do the same thing. The second snippet of code alerts 'old' instead of 'new'
Yousuf Haider
@Yousuf - That's the part I was describing in the answer, `var` won't execute a second time. To see this, you can simplify it down to this: `var y = 'new'; var y; alert(y);​​​​` `y` will still be `new`, it isn't reset. However, `window['y'] = 'new'; var y; alert(y); alert(window.y);` will alert `undefined` then `old`. This is because the first alert refers to the more local `y`, window.y is a different variable.​
Nick Craver
I am trying to understand what you mean by "var won't initialize a variable twice, but it will overwrite one not initialized the first time, which the window['y'] style does, adding it to the window object. "Does this mean that window.y and y are different objects. I thought (incorrectly maybe) that doing window.y or window['y'] meant creating a global variable called y.
Yousuf Haider
@Yousuf - That's the difference, `var y` is not the same as `window.y`, they are separate variables, the `var y` being the more local of the two in the scope.
Nick Craver
@Nick - So what you're saying is that creating a property on the Window object is not equivalent to declaring a global variable. If that is the case then can properties declared on the window object (for eg. window.y) be accessed directly or do you have to use window.y to refer to them.
Yousuf Haider
@Yousuf - You can access it directly, like this: `window['y'] = 'new'; alert(y);` **provided that** there isn't a more local variable with the same name, then you'll get that local variable instead.​
Nick Craver
Aah! Is there some place where this sort of thing is documented in detail. Thanks for the answers.
Yousuf Haider
@Yousuf - There is the spec itself (depending on which version you are running, depends on the browser)...but I'd suggest this for a more practical description of various cases like you've run into here: http://www.digital-web.com/articles/scope_in_javascript/
Nick Craver
A: 

You cannot "redeclare" variables like that within the same scope in JS.

var x = "foo"
function a()
{
  alert(x); // undefined
  var x;
}

In function a, the variable x is local because it has var x. It doesn't matter if it comes before or after the usage.

Likewise:

function b()
{
  var z = 1;
  if (true)
  {
    var z = 2;
  }
  alert(z); // 2
}

because there is no such thing as "block" scope either.

konforce
The last statement is not entirely correct, you can use `let()` to get block scoping.
Nick Craver
You can redeclare it, if the redeclaration occurs at the same scope level. `var x = "foo"; var x; alert(x);`
Matthew Flaschen
@Nick, true, but I'm limiting myself to the subset of JavaScript as implemented by all major browsers. @Matthew, what do you expect that to display?
konforce
@Nick, `let` is a proprietary Mozilla extension, and it will work only on their *JavaScript (TM) 1.7* engines (SpiderMonkey, Rhino)
CMS
@CMS - I wouldn't call it "proprietary" (as it's in the 1.7 spec), Mozilla officially manages javascript...granted their engines typically support new specs before others or this same reason, as is the case here.
Nick Craver
@Nick, I call it proprietary because it isn't part of the ECMAScript Specification, and we will probably never see those language extensions implemented on other engines like JavaScriptCore (*Safari*), V8 (*Chrome*), Carakan (*Opera*), JScript (*IE*) etc...
CMS
@CMS - I see your point...though forgive me in the case of `let()` if I hope you're wrong :) There are a lot of tricky corner cases I've seen some of these additions help the readability/simplicity quite a bit.
Nick Craver
+1  A: 

The var statement is subject of hoisting, this means that when the code enters in execution context (just before the actual runtime), the var and function statements are made available to its enclosing scope.

Your code actually gets evaluated as this:

First example:

var y;
window['y'] = 'old';

if (!y) y = 'new';

alert(y);

Second example:

var y;
y = 'old';

if (!y) y = 'new';

alert(y);

With the var statement hoisted, you see actual behavior that the code is having.

See also:

CMS
i learned something today...
W_P
I didn't think that hoisting happened across files, but I suppose that makes sense since they are executing in the same scope.
Justin Johnson
After doing some testing, it doesn't seem to be the case.
Justin Johnson
@Justin, right, I answered before the user edited, the issue with multiple `script` elements seems to be that IE will re-set to `undefined` an existing variable, when a `var` statement is used on a separate `script` tag...
CMS
Ah, that makes more sense. It seems then that this is a bug/"new feature" in IE.
Justin Johnson
+1  A: 

? I just tested your code and it shows "old", and I've tested FF, Chrome, Safari (PC), and IE8.

Look here: http://jsbin.com/ifare/edit

RussellUresti
Try it here : http://jsfiddle.net/tV2mj/
Yousuf Haider
@Russell same for me....
W_P
Yes, if the first snippet is run at the global scope level, `window['y']` is equivalent to `var y`, so it does alert old. The jsfiddle is *not* run at the global scope, but rather in a function. Probably Yousuf's original code was in a function too. See view-source:http://fiddle.jshell.net/yaQYn/show/light/
Matthew Flaschen
why is doing window['y']='old' different when doing it inside a function as opposed to in the global scope ?
Yousuf Haider
Yousuf, `window['y']` is the same. It's the `var y` that's different (in a function, `var y` creates a new variable that hides the global unless you use `window`)
Matthew Flaschen
It's weird that jsFiddle gets you "new". I created just a plain HTML page locally to test this, and I still get "old" when it's just straight from a page.
RussellUresti
@Matthew - Right, but var y was being declared directly inside a script file. It was not inside a function. That is the point I am trying to make. Since it wasn't inside a function then why is it overriding the old value (since it should be treated as a redeclaration, unless based on Nick's answer those are 2 different variables)
Yousuf Haider
Yousuf, if you run your top snippet (from the question) as is in a script file, it will alert old.
Matthew Flaschen
@Matthew - Please note my update to the original question.
Yousuf Haider