2010-04-14 85 views
1

我有一天遇到了一个有趣的问题,并想知道是否有人可以阐明为什么会发生这种情况。这是我在做什么(为了这个例子的目的,我已经淡化了这个例子):Javascript redeclared全局变量覆盖旧值

  • 我使用方括号表示法创建一个全局作用域变量并为其赋值。
  • 后来我声明了一个与我刚才创建的名称相同的变量。注意我没有分配一个值。由于这是同一个变量的重复声明如下描述的旧值不应该被重写: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 
    
  • 的问题是,旧的价值实际上并获得被覆盖的,并在上面如。该警报显示“新”而不是“旧”。为什么?

我想另一种方式来说明我的问题是如何在从下面的代码语义方面的不同,上面的代码:

//create global variable 
var y = 'old'; 

//redeclaration of the same variable 
var y; 

if (!y) y = 'new'; 

alert(y); //shows Old 

更新1:基于一些评论和回答我正在改写这个例子,以更加反映我原来的问题。

与以下内容创建2个JavaScript文件: 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 

在HTML文件中包含这2个文件

<html> 
<head></head> 
<body> 

    <script type="text/javascript" src="my.js"></script> 
    <script type="text/javascript" src="my2.js"></script> 

</body> 
</html> 

打开此页面Firefox和Chrome提醒“老”,这是预期的行为。然而,在IE 8的页面实际上将警报 '新'

更新2问题搬到这里:Redeclared javascript global variable overrides old value in IE

+1

你简单化了,一定发生了,所有的代码是在功能部分,提供无功雅不同范围比window.y – kennebec 2010-04-14 02:35:08

+0

你的更新应该是一个新的问题,特别是因为它是浏览器特定的。 – 2010-04-14 04:31:58

回答

0

当你与var y;重新声明y,它现在是不确定的,所以if(!undefined)计算结果为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不会初始化变量的两倍,但它会覆盖一个未初始化的第一次(因为它是一个新的,更局部变量),其中window['y']风格呢,加它到窗口对象。以此为例:

//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 
+0

如果这是真的,为什么第二个代码片段不会做同样的事情。代码中的第二个代码段提醒'old'而不是'new' – 2010-04-14 02:05:23

+1

我想了解你的意思,“var不会初始化一个变量两次,但它会覆盖第一次未初始化的窗口[' y']风格,将它添加到窗口对象中。“ 这是否意味着window.y和y是不同的对象。我认为(可能不正确)做window.y或window ['y']意味着创建一个名为y的全局变量。 – 2010-04-14 02:12:32

+0

@Yousuf - 这就是区别,'var y'与'window.y'不一样,它们是单独的变量,'var y'是范围中两个地方中更多的地方。 – 2010-04-14 02:13:55

0

您不能在JS中的同一范围内“重新声明”类似的变量。

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

在功能a,变量x是局部的,因为它有var x。它在使用之前还是之后并不重要。

同样:

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

因为为 “块” 的范围没有这样的东西要么。

+0

最后一个陈述并不完全正确,您可以使用let()来获得块范围。 – 2010-04-14 02:16:51

+0

如果重新声明发生在同一范围级别,您可以重新声明它。 'var x =“foo”; var x; alert(x);' – 2010-04-14 02:17:03

+0

@Nick,真实,但我限制自己的所有主流浏览器实现的JavaScript的子集。 @Matthew,你期望展示什么? – Matthew 2010-04-14 02:36:03

1

var语句就受吊装的,这意味着当代码enters in execution context(只是实际运行时间之前),varfunction报表提供给它的封闭范围。

你的代码实际上被评为本:

第一个例子:

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

if (!y) y = 'new'; 

alert(y); 

第二个例子:

var y; 
y = 'old'; 

if (!y) y = 'new'; 

alert(y); 

随着var声明升起,你看到的实际行为,该代码有。

参见:

+0

我今天学到了一些东西...... – 2010-04-14 02:32:11

+0

我并不认为跨文件发生吊装,但我认为这是有道理的,因为它们在相同的范围内执行。 – 2010-04-14 05:23:30

+0

经过一番测试,似乎并不是这样。 – 2010-04-14 05:37:06

1

?我只是测试了你的代码,它显示“老”,我测试了FF,Chrome,Safari(PC)和IE8。

看看这里:http://jsbin.com/ifare/edit

+0

在这里尝试: http://jsfiddle.net/tV2mj/ – 2010-04-14 02:26:23

+0

@Russell同样适用于我...... – 2010-04-14 02:28:05

+2

是的,如果第一个代码段在全局范围级别运行,则window ['y']'是相当于'var y',所以它确实提醒老了。 jsfiddle不是在全局范围运行,而是在一个函数中运行。也许Yousuf的原始代码也在一个函数中。请参阅view-source:http://fiddle.jshell.net/yaQYn/show/light/ – 2010-04-14 02:28:27