クロージャを説明するために、共通例えばループであります
ため(VAR I = 1; I <= 5; I ++ ){ のsetTimeout(関数タイマー(){ にconsole.log(I); }、 0 ) }
遅延コールバック関数は、ループの実行、変数の値は6となっているときに、サイクルの終わりまで実行されるため、各時間が出力6であろう。私たちは、実行時のキャプチャでのループの各反復は、自分自身に私のコピーを与えると信じています。しかし、原則的範囲によると、呼び出しは同じIです。これは、一つだけ私を持っています。遅延関数がコールバックがサイクルを使用することなく、5回繰り返した定義されている場合、同じコードは以下と等価です
VAR iは1 = 。 setTimeout(関数タイマー(){ にconsole.log(I); }、 0 ) iは 2 = 。 setTimeout(関数タイマー(){ にconsole.log(I); } 0 )、 iが 3 = 。 setTimeout(関数タイマー(){ にconsole.log(I); }、 0 ) iは 4 = 。 setTimeout(関数タイマー(){ にconsole.log(I); } 0 )、 iが 5 = 。 setTimeoutメソッド(関数タイマー(){ にconsole.log(I)。 }、 0 ) iは 6 =。
6出力の5倍。私たちは、より多くのスコープの閉鎖は、iのそれぞれへの参照を保持している必要があります
ため(VAR I 1 =; I <= 5; I ++ ){ (関数(){ のsetTimeout(関数タイマー(){ にconsole.log(I); }、 0 ) })() }
これは、スコープの層が追加されますが、スコープは、それは空だった、それは独自の変数を必要とし、iの値を格納するために使用します
ため(VAR I = 1; I <= 5; I ++ ){ (関数(){ VARの J = I;
のsetTimeout(関数タイマー(){ にconsole.log(J); }、 0 ) })() }
ライン、それができ通常の作業。私たちは、このコードにいくつかの改良を行うことができます。
ため(VAR I 1 =; I <= 5; I ++ ){ (関数(J){ のsetTimeout(関数タイマー(){ にconsole.log(J); }、 0 ) })(I) }
各繰り返しは、新しいスコープがそのようにコールバック関数は、内部変数へのアクセスを所有している遅延する生成します。言い換えれば、我々はすべての必要性、各反復ブロックスコープ、ブロックスコープをハイジャックするために使用することができましょう。基本的にブロックスコープの範囲に変換され、閉じることができ、
以下のために(iは1 =せ; I <= 5; iが++ ){ せJ = I。 setTimeout(関数タイマー(){ にconsole.log(J); }、 0 ) }
多層スコープ効果を有するそのような閉鎖は同じです。しかし、let文のためのループの頭部は特別な振る舞いを持つことになり、変数はループ内でより順次よりも宣言されているように、この動作は、各繰り返し文。
以下のために(iは1 =せ; I <= 5; I ++ ){ のsetTimeout(関数タイマー(){ にconsole.log(I)を }、 0 ) }
クール、ブロックスコープとクロージャ一緒には無敵することができます