2015-10-19 88 views
0

我遇到了以下問題:爲什麼封閉值會丟失?

function Parent(value) { 
    var callback = function() { 
     console.log(value); 
     //actually the following line was found in the code 
     var value; //<- hoisting, takes effect first 
    } 
    callback(); 
} 

Parent(); //undefined 
Parent('Wow!'); //undefined, closure value was lost?! 

兩個上級呼叫記錄「未定義」的消息,但我真的希望看到「哇!」第二次通話的價值。

問題都可以在這裏重現:http://jsfiddle.net/5tgsj37e/3/

相關問題:Why does this closure-scoped variable lose its value?

+1

爲什麼你有'console.log('value');'?這不會每次都記錄「價值」嗎?它在控制檯中是「未定義的」嗎?而且,正如@charlietfl所說,「url」沒有定義,所以AJAX可能根本不起作用。這是你的完整代碼嗎? –

+3

哪裏定義了「url」?另外'Parent()'不會返回任何東西,所以它沒有意外的記錄未定義。你到底想要在這裏發生什麼? – charlietfl

+0

已更新var url = anyUrl;和console.log(value); – Spirit

回答

0

的原因是提升:

(function Parent(value) { 
    var child = function() { 
     console.log(value); 
     var value; //hoisting clears closure value 
    } 
    child(); 
}('Wow!')); 

雖然沒有大礙:

(function Parent(value) { 
    var child = function() { 
     console.log(value); 
     //var value; 
    } 
    child(); 
}('Wow!')); 

我沒有注意到父函數VAR值昨天。

代碼示例:http://jsfiddle.net/5tgsj37e/3/


關於代碼風格的其他注意事項。

嚴格模式:將孩子放在父母之外將會創建一個全局。因此,在使用閉包時,應將「嚴格使用」嚴格模式視爲一種良好做法。

顯式關閉聲明如果要在子函數中使用閉包值,最好將Child明確包裝到閉包中。如果有一天你的孩子開始生活在父母之外,這將阻止全局變量的創建。這也會引發一個沒有價值的錯誤。

(function Parent(value) { 
    (function(childValue) { 
     var child = function() { 
      console.log(childValue); 
     } 
     child(); 
    )(value)); 
}('Wow!')); 

備註關閉:關閉是每個函數調用創建的,而不是每個函數聲明。

2

在這個例子中,Parent沒有return語句,因此總是返回undefinedParent也不會自行調用console.log,因此不會將任何內容記錄到控制檯。在其中創建並分配到var callback的匿名函數調用console.log。然後通過您的ajaxCall函數將此成功回調傳遞給jQuery.ajax()

匿名callback函數將在異步ajax請求成功後調用。對於AJAX請求,當然根據jQuery documentation成功。

至於結果似乎不可能再現與代碼是,或許有你的Parent功能的地方,刪除value參數或以其他方式將其設置爲undefined額外的代碼。由內部函數關閉的參數和變量不會被垃圾收集,除非它們具有0引用計數。

+0

而在我的情況字符串值似乎是垃圾收集。 – Spirit

+0

正在使用什麼JavaScript引擎? – Nicholas

+0

這是Chrome瀏覽器。我已經刪除了ajax調用,問題仍然被複制。所以這是一個關閉問題。 – Spirit