function f1(){
var n = 999 ;
nAdd = function(){ n = 1; }
function f2(){
alert(n);
return
}
ここでのクロージャは f1 で、変数 n と関数 f2 を閉じます。
まず nAdd を無視して、元の外観を維持してこの関数を書き直してみましょう。
function f1(){
var n = 999 ;
var f2 = function(){alert(n) };
var result =
result(); >
js の各変数は関数単位にカプセル化されます。関数内で変数が見つからない場合、関数はその変数が存在する前の単位 (コンテキスト) を先頭まで検索します。 -レベルのウィンドウドメイン。
このとき疑問が生じます。検索処理は関数参照位置から始まるのか、それとも関数本体定義位置から始まるのか?
上記のコードでは結果の領域はwindowとなっていますが、実際に出力される結果はf1内のn値なので、変数検索の開始点は関数本体が定義されている位置であると言えます。
ここで、nAdd (コードの最初の部分) を見てみましょう。ご存知のとおり、キーワード var を使用せずに定義された変数はデフォルトでウィンドウ ドメインに入ります。そのため、nAdd は実際には window.nAdd になります。これは次のコードと同等です:
コードをコピーします
var n = 999; }
function f2(){
alert(n); 🎜>}
return function(){ warning(n) };
}
結果の分析によれば、nAdd の実行は n の値に影響します。 f1.
コードをコピーします
alert(n);関数(){ アラート (n) };
var 結果 = f1();
nAdd(); 🎜>
このコード実行の最終出力結果は 1000 です。
この状況をもう一度見てください:
コードをコピーします
コードは次のとおりです:
function f1(){
var n = 999;
nAdd = function(){ n = 1; }
function f2(){
実行プロセスを簡単に説明します:
位置 p1 で、f1 は匿名クロージャ A をカプセル化し、関数 A:f2 を返します。次に、A:f2 が実行され、A:f2 は変数 A:n を出力し、結果は 999 になります。
同時に、A のクロージャーに関数として nAdd が代入され、次の行で nAdd が実行され、A:n の値が 1 に設定されます。
位置 p2 で、f1 は匿名クロージャ B をカプセル化します。実行される操作はすべてクロージャ B に対して行われます。その場合、B:f2 の出力は B:n となるため、最終結果は 999 のままです。
A と B は 2 つの独立した「パッケージ」であり、相互に影響しません。
関数の呼び出し部分を書き換えます:
コードをコピーします
コードは次のとおりです。
関数 f1(){
var n = 999;
nAdd = function(){ n = 1; }
関数 f2(){
alert(n) );
}
関数(){ アラート(n) };