Javascript redeclared global variable overrides old value
I ran into开发者_StackOverflow社区 an interesting issue the other day and was wondering if someone could shed light on why this is happening. Here is what I am doing (for the purposes of this example I have dumbed down the example somewhat):
- I am creating a globally scoped variable using the square bracket notation and assigning it a value.
Later I declare a var with the same name as the one I just created above. Note I am not assigning a value. Since this is a redeclaration of the same variable the old value should not be overriden as described here: http://www.w3schools.com/js/js_variables.asp
//create global variable with square bracket notation window['y'] = 'old'; //redeclaration of the same variable var y; if (!y) y = 'new'; alert(y); //shows New instead of Old
The problem is that the old value actually does get overriden and in the above eg. the alert shows 'new' instead of 'old'. Why ?
I guess another way to state my question is how is the above code different in terms of semantics from the code below:
//create global variable
var y = 'old';
//redeclaration of the same variable
var y;
if (!y) y = 'new';
alert(y); //shows Old
Update 1 : Based on the some of the comments and answers I am rephrasing the example to be more reflective of my original problem.
Create 2 javascript files with the following content : Script1
//create global variable with square bracket notation
window['y'] = 'old';
Script2
//redeclaration of the same variable
var y;
if (!y) y = 'new';
alert(y); //shows New instead of Old in IE
Include these 2 files in your html file
<html>
<head></head>
<body>
<script type="text/javascript" src="my.js"></script>
<script type="text/javascript" src="my2.js"></script>
</body>
</html>
Opening this page in Firefox and Chrome alerts 'old' which is the expected behavior. However in IE 8 the page will actually alert 'new'
Update 2 question moved here : Redeclared javascript global variable overrides old value in IE
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
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.
? 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
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:
- Variable Instantiation
精彩评论