2012-11-29 68 views
6

在下面的代碼:重新聲明JavaScript變數

var greeting = "hi"; 

function changeGreeting() { 
    if (greeting == "hi") { 
     var greeting = "hello"; 
    } 

    alert(greeting); 
} 

changeGreeting();​ 

... greeting是不確定的。但是,如果我刪除var並改變changeGreeting()這樣:

function changeGreeting() { 
    if (greeting == "hi") { 
     greeting = "hello"; 
    } 

    alert(greeting); 
} 

...我得到預期的「hello」。

我永遠不會在我的代碼中重新聲明這樣的變量,但爲什麼會發生這種情況?

回答

27

JavaScript變量具有函數範圍。因此,該函數中var greeting的存在將聲明一個本地greeting變量,在if條件中提及時,該變量將是未定義的:全局變量在函數內部不可見,被本地遮蔽。因此,if不會發生,不會發生賦值爲hello,該變量仍然未定義。

在第二個示例中,您始終使用全局變量,但它不會被局部變量遮蓋(因爲函數內部沒有var greeting),並且事情按預期工作。

+3

+1那麼措辭清楚的答案。 – Aesthete

+0

確實爲你的先生。 –

+0

@bfavaretto:我認爲'var greeting'是一個錯誤,應該是'var currentSize'全局變量聲明(在第一個例子中已經被遮蓋了,並且在第二個例子中被使用了)。否則,這將是完全不相關的例子。 – Amadan

-1

在你的第一個代碼片段中,你正在檢查全局變量,它不存在 - >如果條件不通過。

看看這個JavaScript的範圍和如何與變量工作Javascript garden - function scopes

+1

第一個片段是_not_檢查一個全局變量,函數體包含該變量的'var'聲明,該變量被懸掛在頂部。它檢查本地'var currentLength;'< - 未定義的變量,在函數返回 –

+0

後被GC'ed,你是對的。我完全清除了懸掛:/ – rdamborsky

6

這很簡單:JS扯起變量聲明當前作用域的頂部,但是任何操作(包括轉讓)不(當然在同一範圍內,請參閱第二個案例解釋)。所以,你的代碼片段轉換爲

(function() 
{ 
    var currentSize;//undefined 
    if (currentSize == 'hi')//always false 
    { 
     currentSize = 'hello';//assignment that will never be 
    } 
    alert(currentSize);//alerts undefined, of course 
}()); 

通過留出了var,進入範圍掃描(檢查變量在全球範圍內被宣佈)。 不幸的是,在這樣做時,第一次使用var的上下文丟失了(在分支中),並且分配也被掛起。隱含的全球翻譯爲
感謝上帝,這是不正確的。我以爲是因爲我在控制檯上測試了一些似乎證實了這一點的東西。在這種情況下,@amadan是正確的:您使用的是全局變量(當我發佈這個變量時,在您的代碼段中錯誤地稱爲greeting)。我將在下面留下代碼(更正它)以顯示實際上隱含的全局變量,希望有助於某人理解JS中的範圍/範圍掃描。

var currentSize = 'hello'; 
//well, actually implied globals can be deleted, so it's more like 
Object.defineProperty(this,'currentSize',{value:undefined, 
              writable:true, 
              enumerable:true, 
              configurable:true}); 
(function() 
{ 
    if (currentSize == 'hi')//always false 
    {//this still doesn't get executed 
     currentSize = 'hello';//assignment that will never be 
    } 
    alert(currentSize);//alerts undefined 
}()); 
+0

關於變量範圍的一個很好的解釋答案我從中學到了很多東西來糾正我關於JS中變量作用域的概念 –