2014-05-04 24 views
0

我已經2段,爲什麼第一個給出的值第二給出了不確定爲什麼有時在調用變量後定義變量不會給出未定義?

片段1:

function sayAlice() { 
    var sayAlert = function() { alert(alice); } 
    var alice = 'Hello Alice'; 
    return sayAlert; 
} 
var hi = sayAlice() ; 
hi();//alert Hello Alice 

片段2:

alert(i); // alert undefined 
var i = 1; 
+1

切換第二個示例中的行,它工作 – Sebastian

+0

是的......我知道。我想知道爲什麼在第一個代碼段工作 – Blake

+0

請參閱我在答案中提供的鏈接,您將學習。 –

回答

1

這是因爲在第二個片段中,變量「i」是不是在警報的時刻定義被執行,但在第一個片段,什麼情況是,在該行

var sayAlert = function() { alert(alice); } 

你正在將'sayAlert'定義爲一個函數,但是這個函數在那一刻不會被執行。之後,你定義了變量'alice',之後返回'sayAlert',並且在那一刻,執行警報的時候,變量'alice'已經有了一個值。

0

試試這段代碼,你會得到完全不同的結果...

function sayAlice() { 
    var sayAlert = function() { alert(alice); } 
    return sayAlert; 
    var alice = 'Hello Alice'; 
} 

因爲函數調用時未定義。在你的例子中,定義了alice

1

你的問題是這樣的:

爲什麼有時會調用該變量不 給未定義的定義後的變量?

然後你提供這作爲例子:

alert(i); // alert undefined 
var i = 1; 

它提醒undefined因爲你發出定義ialert()之前。

而在第一個例子:

function sayAlice() { 
    var sayAlert = function() { alert(alice); } 
    var alice = 'Hello Alice'; 
    return sayAlert; 
} 
sayAlice()() //alert Hello Alice 

相同的行爲是可以預料的,但它似乎是叫sayAlice你奇怪的方式與()()發生兩次。這基本上意味着它可能會很快發生,但第一次調用sayAlice()將設置alice變量,但alert最有可能發生在通過sayAlice()()調用的第二次迭代中。

等等。再看一遍,這就是第一個例子中發生的事情。這只是sayAlert定義爲一個函數,但實際上並沒有運行:

var sayAlert = function() { alert(alice); } 

但你這樣做:

var alice = 'Hello Alice'; 

其中分配一個值alice。然後你最後這樣做:

return sayAlert; 

在前兩項之後會發生哪種情況。意思是,在第三行你定義了一個函數,然後定義了一個變量,但它只在最後一行中出現。

這對我有意義。但sayAlice()()與雙()似乎很奇怪。

+1

我有兩個片段,第一個不給出undefined,第二個片段不對, – Blake

+0

@Blake正確。有趣的謎題。在最新的編輯中查看我的分析。 – JakeGould

+0

@JakeGould - 這不是一個難題。它記錄了JS closure的行爲。 –

1

在運行之前,所有變量聲明都被javascript解釋器移動到其範圍的頂部。這意味着,像這樣:

function sayAlice() { 
    var sayAlert = function() { alert(alice); } 
    var alice = 'Hello Alice'; 
    return sayAlert; 
} 
sayAlice()() //alert Hello Alice 

等同於:

function sayAlice() { 
    var sayAlert, alice; 
    sayAlert = function() { alert(alice); } 
    alice = 'Hello Alice'; 
    return sayAlert; 
} 
sayAlice()() //alert Hello Alice 

當你調用sayAlice()()它首先解決sayAlice()返回你的函數sayAlert,綁定到變量alice具有的價值'你好,愛麗絲'。只要內部函數可以訪問外部變量,該變量將保留其範圍。因此,分配sayAlert後的行即alice = 'Hello Alice'會修改sayAlert函數引用的變量。那麼在調用的時候,你會得到預期的結果「Hello Alice」。

+0

「所有變量聲明都移動到其範圍的頂部......」有趣。看看我的答案。當'var sayAlert = function(){alert(alice); }'不僅僅是一個變量被分配了一個函數,而是直到'return sayAlert;'函數才被執行。 – JakeGould

+1

我修改了我的答案。它的要點是否定的:變量沒有分配給該函數。該函數讀取該變量的引用,該變量在聲明該函數後可能已在其他地方更改過。 – sahbeewah

+0

很好的解釋! – JakeGould