2010-04-14 137 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