我以爲我用Javascript理解了閉包,但顯然我沒有。以下代碼不起作用。如何在延遲1秒後打印出控制檯中從0到9的所有數字?目前它只打印「未定義」十次。帶有Javascript回調的閉包
注意:我不想尋找一個簡單的鍛鍊來延遲打印數字。這個問題是關於理解閉包。
<script>
for(var i=0;i<10;i++){
setTimeout(function(i){console.log(i)}, 1000)
}
</script>
我以爲我用Javascript理解了閉包,但顯然我沒有。以下代碼不起作用。如何在延遲1秒後打印出控制檯中從0到9的所有數字?目前它只打印「未定義」十次。帶有Javascript回調的閉包
注意:我不想尋找一個簡單的鍛鍊來延遲打印數字。這個問題是關於理解閉包。
<script>
for(var i=0;i<10;i++){
setTimeout(function(i){console.log(i)}, 1000)
}
</script>
閉包是在JavaScript中很重要,但要了解你是closing
正是在這一點很重要。重做你當前的代碼(種類)。
function(){
var i;
for(i=0;i<10;i++){
setTimeout(function(){
console.log(i);
}, 1000);
}
}
在這個例子中,你的代碼基本上是關閉了var i;
,這意味着當定時器運行時,它會讀取該的var i;
值並打印出來。在這種情況下,如您所見,定時器運行時,循環已完成,值爲10
。
你想要做的是創建一個新的函數範圍,在特定的時間捕獲i
的值。
function(){
var i;
for(i=0;i<10;i++){
(function(iInner){
setTimeout(function(){
console.log(iInner);
}, 1000);
})(i);
}
}
這個例子將創建一個新的匿名函數,然後在循環立即調用它,並傳遞的i
當前值到它,所以,當你的計時器讀取iInner
,它會讀取這可是價值傳遞給函數,而不是來自var i;
的值。如果需要,您也可以撥打iInner
i
,但爲了清晰起見,我使用了兩個不同的名稱。
還有一些助手可以使用,例如.bind
,它們本質上會自動爲您創建一個新的匿名函數,並傳遞像這樣的參數。
function(){
var i;
for(i=0;i<10;i++){
setTimeout(function(iInner){
console.log(iInner);
}.bind(null, i), 1000);
}
}
<func>.bind
將採取i
的值,並返回調用時通過對<func>
那些ARGS一個新的功能,您就不必創建嵌套的另一層。
您已經定義了回調函數取參數i
,這是掩蓋在聲明for循環closurable i
。因此,將其更改爲:
<script>
for(var i=0;i<10;i++){
setTimeout(function(){console.log(i)}, 1000)
}
</script>
編輯:對不起,我不看你的問題的一般意圖。就封閉方式而言,函數對象捕獲對函數體內引用的封閉範圍中的任何變量的引用,該引用不綁定到主體內的任何局部變量(參數或顯式var
聲明) 。這就是爲什麼你的原始嘗試不起作用; i
綁定到本地參數。
功能對象不會不捕獲值該合攏變量具有在被定義的功能的時間;它捕獲了一個參考它。因此,您無法迭代單個變量(我正在討論在for循環中聲明的var i
),意圖是爲每個後續函數定義關閉值。價值觀沒有關閉;變量是。
但是,您可以通過關閉一個臨時本地來有效地關閉一個值,該臨時本地具有您要在定義該函數時捕獲的值。它需要創建一個新的功能範圍和界定範圍內的closuring功能,圍繞本地(函數參數)closuring有你想要的值:
<script>
for (var i_outer = 0; i_outer < 10; ++i_outer)
setTimeout((function(i_inner) { return function() { console.log(i_inner); }; })(i_outer), 1000);
</script>
這是你怎麼做。您創建了一個IIFE(立即調用的函數表達式),該函數返回一個打印到控制檯的函數。記住我的價值,應該被內在的功能所吞噬,通過將它作爲一個參數來傳遞。
setTimeout需要一個「函數」作爲第一個參數,這就是我們從IIFE返回函數的原因。
for(var i=0;i<10;i++){
setTimeout((function(i) {
return function() {
console.log(i);
}
})(i), 1000)
}
感謝
不!這只是打印10次。這就是爲什麼我們需要關閉。 – 2014-12-06 20:46:36