3

以下の 2 つの例を見てください。どちらの例でも、変数iには 0 ~ 9 が割り当てられています。最初の例では、タイムアウト関数が呼び出されるまでに、既に値 9 が割り当てられています。タイムアウトが設定されたときのi値はわかりません。i

for(var i = 0; i < 10; i++) {
    var callback = function() {
        alert('The first test returns: ' + i);
    };

    if(i === 0) setTimeout(callback, 2000);
}

2 番目のオプションでは、値を新しいコンテキストに渡すことで値を永続化できiます (この用語が正しくない場合は訂正してください)。

for(var i = 0; i < 10; i++) {
    var callback = (function(i) {
        return function() {
            alert('The second test returns: ' + i);
        }
    })(i);

    if(i === 0) setTimeout(callback, 2000);
}

2 番目の例は、私が期待する値を示しています。では0、ガベージ コレクションに関する限り、これはどのように機能するのでしょうか。GC はどの時点でこの値を削除しますか? コールバック関数の最後に? それとも、ある種のメモリリークが発生しますか?

4

1 に答える 1

4

最初の例でcallbackは、 は関数function(){alert('...' + i);}であり、は が定義さiれているスコープ内の変数callback、つまりiinfor(var i = 0; ...)です。

setTimeout(callback, 2000)が呼び出された場合でも、ループ全体を実行するのに十分な時間でiある02000ms 後に 10 になり、呼び出されたときに表示されます。foricallbackThe first test returns: 10

ただし、クロージャーが作成される 2 番目の例では、callbackそれ自体はまだfunction(){alert('...' + i);}ですが、無名関数の引数iはその親スコープをシャドウするため、iincallbackは無名関数の引数であり、 inではiありません。ifor(var i = 0; ...)

JavaScript は値による呼び出しを使用するため、が によって設定さiれると「固定」されます。これにより、引数を持つ無名関数が作成され、すぐに値によって適用されます( 内)。callback(function(i){...}(i))iifor(var i ...)

ここでは GC の役割はありません。(メモリ使用量とタイミングを除いて、GC による異なる動作は、GC にバグがあることを意味します。)

于 2013-08-03T06:15:49.403 に答える