JavaScript閉包與匿名函數 - JavaScript closures vs. anonymous functions

語言: CN / TW / HK

問題:

A friend of mine and I are currently discussing what is a closure in JS and what isn't.我的一個朋友和我目前正在討論JS中的閉包,什麼不是閉包。 We just want to make sure we really understand it correctly.我們只想確保我們真正正確地理解了它。

Let's take this example.讓我們來看這個例子。 We have a counting loop and want to print the counter variable on the console delayed.我們有一個計數循環,並希望延遲在控制枱上打印counter變量。 Therefore we use setTimeout and closures to capture the value of the counter variable to make sure that it will not print N times the value N.因此,我們使用setTimeout閉包來捕獲計數器變量的值,以確保它不會輸出N倍於值N的值。

The wrong solution without closures or anything near to closures would be:沒有閉包或接近閉包的錯誤解決方案是:

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);
    }, 1000);
}

which will of course print 10 times the value of i after the loop, namely 10.這當然會在循環後輸出i 10倍的值,即10。

So his attempt was:因此,他的嘗試是:

for(var i = 0; i < 10; i++) {
    (function(){
        var i2 = i;
        setTimeout(function(){
            console.log(i2);
        }, 1000)
    })();
}

printing 0 to 9 as expected.按預期打印0到9。

I told him that he isn't using a closure to capture i , but he insists that he is.我吿訴他,他沒有使用閉包捕獲i ,但他堅持認為自己是。 I proved that he doesn't use closures by putting the for loop body within another setTimeout (passing his anonymous function to setTimeout ), printing 10 times 10 again.我通過將for循環體放在另一個setTimeout (將他的匿名函數傳遞給setTimeout )中,再次打印10乘10來證明他沒有使用閉包 The same applies if I store his function in a var and execute it after the loop, also printing 10 times 10. So my argument is that he doesn't really capture the value of i , making his version not a closure.如果我將他的函數存儲在var並在循環執行它,並打印10次10​​,則同樣適用。所以我的觀點是他並沒有真正捕獲i的值,因此他的版本不是閉包。

My attempt was:我的嘗試是:

for(var i = 0; i < 10; i++) {
    setTimeout((function(i2){
        return function() {
            console.log(i2);
        }
    })(i), 1000);
}

So I capture i (named i2 within the closure), but now I return another function and pass this around.因此,我捕獲了i (在閉包中命名為i2 ),但是現在我返回了另一個函數並將其傳遞給周圍。 In my case, the function passed to setTimeout really captures i .就我而言,傳遞給setTimeout的函數實際上捕獲了i

Now who is using closures and who isn't?現在誰在使用閉包,誰沒有?

Note that both solutions print 0 to 9 on the console delayed, so they solve the original problem, but we want to understand which of those two solutions uses closures to accomplish this.請注意,這兩種解決方案在控制枱上都延遲輸出0到9,因此它們可以解決原始問題,但是我們想了解這兩種解決方案中的哪一種使用閉包來完成此任務。


解決方案:

參考一: https://stackoom.com/question/sFkm
參考二: JavaScript closures vs. anonymous functions
「其他文章」