2016-07-28 5 views
1
function f1() {     
    var n = 999;     
    nAdd = function() { 
     n += 1 
    }     
    function f2() {       
     alert(n);     
    }     
    return f2;   
}   
var result1 = f1(); 
var result2 = f1(); 
var result3 = f1();   

nAdd(); 
result1(); //999 
result2(); //999 
result3(); //1000 

このコード例では、nAdd()という呼び出しが最も近いクロージャにのみ影響するという結論に達しました。JavaScript closure - result3()の出力だけがnAdd()によって影響を受けるのはなぜですか?

例:result3()の出力は1000です。
なぜですか?

答えて

1

nAddに機能が割り当てられているときと関係があります。クロージャを作成すると、ローカル変数の新しい "コピー"(より良い言葉がないため)が作成されることに注意してください。従って、result1nは、result2snと異なり、result3nとは異なります。それらは分離しており、それぞれのクロージャは別のクロージャのnにアクセスできません。この行で

ルック:

nAdd = function() { 
    n += 1; 
} 

これはnAdd新しい閉鎖するたびに割り当てられます。この閉鎖は毎回nの最新の「コピー」にのみ影響します。

あなたがそうしているとき。

var result1 = f1(); // assign nAdd for the first time, referring to result1's n. 
var result2 = f1(); // re-assign nAdd, now it affects result2's n. 
var result3 = f1(); // re-assign nAdd, now it affect result3's n. 

nAdd毎回新しい閉鎖が割り当てられました。前回、nAddにはresult3のnのコピーが割り当てられました。

したがって、nAdd()を入力すると、result3の数字はnとなります。

これは、物事をクリアするかもしれない例です。

function f1() {     
    var n = 999;     
    nAdd = function() { 
     n += 1 
    }     
    function f2() {       
     alert(n);     
    }     
    return f2;   
}   
var result1 = f1(); 
var nAdd1 = nAdd; 
var result2 = f1(); 
var nAdd2 = nAdd; 
var result3 = f1();   
var nAdd3 = nAdd; 

nAdd3(); 
result1(); //999 
result2(); //999 
result3(); //1000 
nAdd1(); 
result1(); // 1000 
nAdd1(); 
result1(); // 1001 
nAdd2(); 
result2(); // 1000 
nAdd(); 
result3(); // 1001 (the most recent nAdd result3's n). 

精巧促進するために、あなたの代わりにこれをしなかったらどうなるか考えてみます。

var result1 = f1(); 
nAdd(); 
var result2 = f1(); 
var result3 = f1();  

result1(); // 1000 
result2(); // 999 
result3(); //999 

またはこの:

var result1 = f1(); 
var result2 = f1(); 
nAdd(); 
var result3 = f1();  

result1(); // 999 
result2(); // 1000 
result3(); // 999 

それはそのnAdd更新が唯一の最も最近の呼び出しのn明らかになりました!

+0

"これは毎回nAddに新しい機能を割り当てます。この機能はたびにnの最新のコピーにのみ影響します。なぜ機能は最新のコピーにのみ影響しますか? – Tommy

+0

@Tommyローカル変数の新しいセットが毎回作成されます。クロージャをnAddに割り当てると、クロージャはローカル変数の最新のセットを参照します。ただし、関数を呼び出すたびにnAddを上書きします。したがって、 nAddは、(result3に代入する)最新の呼び出しの変数のみを参照するため、result3のnにのみ影響します。 result3に割り当てる前にnAdd呼び出しを移動して、出力にどのように影響するかを確認してください。 –

+0

@GiorgianThanks!あなたの答えとEluneの答えはどちらも素晴らしいです!私はそれを扱うと思う。 – Tommy

0

まず、次のことを明確にする必要があります

NADDは、グローバルスコープの関数です。しかし、ローカルスコープ変数nを使用しています。

f1()を再作成するたびに、nAdd関数のポインタが変更されます。

最後に、最も近いf1()クロージャに変更され、nAdd関数内のn変数も最も近いf1()クロージャをポイントします。したがって、最も近い値の値だけを変更することができます。

+0

ありがとう! 'nAdd関数のポインタが変更されます。'とても重要です。私はそれを扱います! – Tommy

関連する問題