2010-12-04 17 views
2

私は、次のコードをお持ちの場合:閉鎖の用語と意味疑い

function foo() 
{ 
    var a = []; 
    for(var i = 0; i < 3; i++) 
    { 
     a[i] = function(x) 
     { 
      return function() 
      { 
       return x; 
      } 
     }(i); 
    } 
    return a; 
} 

私はすべての繰り返しで(I)を呼び出す場合、または私は内側の関数を定義する際にクロージャを作成しますか?

とし、ラムダ式はクロージャーですか?

ありがとうございました。

答えて

1

クロージャは、仮パラメータリストの唯一のメンバーとして定義されたローカル変数xへのアクセス権を持つ関数を返すことによって作成されます。

したがって、a[i]に格納されている関数は、同じスコープ内にあった固有のxを閉じて、アクセスします。この変数は自己呼び出し関数から渡されたこの関数によってのみアクセス可能であるため、クロージャーがあります。

ここでは、匿名関数を呼び出すことは不要なので、ここでは不要であり、オーバーヘッドが追加される方がよいでしょう。代わりに、名前付き関数を宣言し、それを呼び出します。

function foo() 
{ 
    var a = []; 
    function retain_i(x) 
    { 
     return function() 
     { 
      return x; 
     } 
    } 
    for(var i = 0; i < 3; i++) 
    { 
     a[i] = retain_i(i); 
    } 
    return a; 
} 

EDIT:は、あなたの質問に具体的には:私はすべての繰り返しで(i)を呼び出すとき

閉鎖が作成されます...

いいえ、これはクロージャを作成しません。 を返したときにクロージャが作成されるのは、xパラメータの周りで閉じた関数で、それ以外の場合は自己呼び出し関数の外部ではアクセスできません。

この関数を返さなかった場合は、クロージャはありません。

私が与えた修正されたコード例からわかるように、関数の定義/宣言はクロージャを作成しません。むしろアクセスできない変数にアクセスできる他の関数を渡す関数の実行は、クロージャを作成します。

+1

環境モデルによれば、関数*を定義するとクロージャが作成されます。クロージャーが生き残った文脈を越えるかどうかは関係ありません。 – EFraim

1

実行時ではなく、関数を定義するときにクロージャが作成されます。これはレキシカルスコープと呼ばれます。

0

クロージャは、関数定義で作成されます。

従ってあなたの例では、それらは各反復のために作成された - 外側functionが宣言されて初めて、それが起動され第二の時間、内部関数を定義します。

配列のセルiに割り当てられた結果は、iを返す関数です。

他のポスターは、 "字句"スコープと呼ばれていますが、現代の言語のほとんどはそれを使用しているようです。

関連する問題