Javascript redeclared global variable overrides ol

2019-02-20 10:14发布

问题:

I ran into 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

回答1:

? 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



回答2:

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


回答3:

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


回答4:

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.