web-dev-qa-db-ja.com

JavaScriptで「クロージャ」とは具体的に何を指しているのですか?

クロージャが何であるかは理解していますが、closureという用語が正確に何を指しているのかを理解するのに問題があります。多くのウェブサイトで使用されている用語を見てきましたが、実際の定義に同意することはめったにありません。

  • スタックフレームに保持されるのは変数ですか?
  • 返されるのは関数ですか?
  • それは外部関数のスコープですか?
  • 内部(返された)関数のスコープですか?
  • 関数を返した後に変数をスタックフレームに保持するconceptでしょうか?

誰かがclosureの意味を正確に教えてくれますか?

71
Andreas Grech

From JavaScript Closures

2つの1文の要約:

クロージャーは、関数のローカル変数です-関数が戻った後も保持されます。

クロージャは、関数が戻るときに割り当て解除されないスタックフレームです。 (まるで「スタックフレーム」がスタック上ではなくmallocされたようです!)

クロージャーに関する非常に良い記事

Javascript Closures

「クロージャ」は、それらの変数をバインドする(式を「閉じる」)環境とともに自由変数を持つことができる式(通常は関数)です。

クロージャの簡単な説明は、ECMAScriptが内部関数を許可することです。他の関数の関数本体の内部にある関数定義と関数式。そして、それらの内部関数は、すべてのローカル変数、パラメーター、および外部関数内で宣言された内部関数へのアクセスを許可されます。これらの内部関数の1つが、それが含まれていた関数の外部でアクセス可能になると、クロージャーが形成され、外部関数が戻った後に実行できるようになります。その時点で、ローカル変数、パラメーター、および外部関数の内部関数宣言にアクセスできます。これらのローカル変数、パラメーター、および関数の宣言は、(最初​​は)外部関数が戻ったときに持っていた値を持ち、内部関数によって操作される可能性があります。

ここの良い例

JavaScript、クロージャーを処理する時間

45
rahul

これは、別のスコープ内の何かへの1つまたは複数の参照を「保持」する関数です。例えば:

var myArrayOfFunctions = [];

for(var i = 0; i<3: i++)
{
    //Note how the function being defined uses i, 
    //where i lives in the parent's scope, this creates a closure
    myArrayOfFunctions[i] = function(a) { return a + i;}    
}

myArrayOfFunctions[0](5);   //Prints 8 WTF!
myArrayOfFunctions[1](5);   //8 again
myArrayOfFunctions[2](5);   //Well, this 8 was expected

これは、関数が「作成」されたときにiの値をコピーせず、iへの参照を保持するため、関数を呼び出すときに3であるiの現在の値を使用するために発生します。

これはグラフィカルな説明です。

6

私の場合、JSのクロージャーを使用すると、次のことができます。
外部で宣言されていますが、「a」は「b」に追加されても内部関数で引き続き使用できます。

function adder(a){
  return function(b){
    return a + b;
  };
}
var add5 = adder(5);
alert( add5(10) );

JSクロージャを極端に使用する場合は、PUREライブラリ(JSテンプレートエンジン)の ソースコード を確認できます。

4
Mic

変数aとbでクロージャーを作成する次のコードを考えてみます。

closure=(function(){ 

    var a=3
    var b=5 

return  function(operation){ 
          return operation(a,b)
      }
 }())


// The variables a and b are now part of the closure (They are retained even after the outer function returns)


closure(function(x,y){return x+y})  // outputs 8

closure(function(x,y){return x*y}) // outputs 15`

この特定のクロージャは、変数aおよびbを操作する任意の関数をとることができます。

2
sarath joseph

私が知る限り、クロージャーは、親関数のスコープよりも長く存続する別の関数内で定義された関数です。一般的な例はコールバックです:

function delay_message(msg)
{
     setTimeout(function closure() { alert(msg); }, 1000);
}

この場合、上記のfunction closuredelay_messageの本体内で定義されますが、関数定義(および親関数の変数msg)は、delay_message関数呼び出しのスコープよりも長く存続します。

2
intgr

クロージャーは、ネストされた関数宣言または関数式(つまりラムダ式)から作成された関数値であり、その本体には外部(ただしグローバルではない)スコープで宣言された変数への1つ以上の参照が含まれます。

1

基本的に、クロージャは、ローカル環境内の識別子(変数)で閉じられた関数本体です。

1
Mark Ursino

クロージャーとは、別の関数(内部関数)を含む関数(外部関数)を意味します。

クロージャはデータを保護するために使用されます。

クローザーの使用は、以下に提供するビデオリンクでデモンストレーションされます。

https://www.youtube.com/watch?v=w1s9PgtEoJs

0
Abhishek-Saini