2012-03-01 82 views
8

說我有一個簡單的函數,警報消息:爲什麼這個封閉工作?

function callMessage(msg){ 
     alert(msg); 
    } 

現在,當我這樣稱呼它的話,它不工作。拋出錯誤「哎沒有定義」

function sayHi(){ 
     var hey = "hi there" 
     setTimeout("callMessage(hey)", 1000); 
    } 
    sayHi(); 

但是,當我把它叫做一個匿名函數內部它的工作:

function sayHi(){ 
     var hey = "hi there" 
     setTimeout(function(){callMessage(hey);}, 1000); 
    } 
    sayHi(); 

爲什麼是「哎」變量,當我把它裏面的唯一可見匿名函數?

+1

我也嘗試這個; '的setTimeout( 「VAR哎= '您好'; callMessage(嘿嘿)」,1000);' – mindandmedia 2012-03-01 15:49:13

+0

如果我是你,我會讀一些類似 - http://www.digital-web.com/articles/scope_in_javascript/ – 2012-03-01 15:49:31

回答

14

在第一個示例中,在之後,計算代碼計時器已過期,並且當前範圍已保留。 hey在那個時候是未定義的。

第二個示例 - 使用setTimeout的正確方法 - 使用調用setTimeout()時創建的匿名函數。這個匿名函數還會接收當前範圍的副本。

+0

在第二個例子中,封閉體在此之前不會被評估。 – sepp2k 2012-03-01 15:51:23

+2

直到晚些時候它才被執行。第一個*字面*評估('eval()'),沒有提示使用哪個範圍,因爲它的「只是一個字符串」。 – 2012-03-01 15:52:49

+0

這很有道理。我不知道匿名函數有它的父範圍的副本 – levi 2012-03-01 16:03:31

6

「callMessage(嘿)」 是一個字符串,而不是一個封閉。它會在超時運行時進行評估,此時變量hey不在範圍內。

3

這是正常的。

第二個示例創建我們稱之爲夾具,這是一個執行環境。嘿變量變量被保存爲由內存中的匿名函數使用。

在你的第一個例子,哎變量不會被保存在一個固定裝置(因爲JavaScript不能知道你將使用後的變量),因此不能被檢索時,該字符串評估