「クロージャー」とは何ですか?質問する

「クロージャー」とは何ですか?質問する

カリー化について質問したところ、クロージャについて言及されました。クロージャとは何ですか? カリー化とどのように関係していますか?

ベストアンサー1

変数のスコープ

ローカル変数を宣言すると、その変数にはスコープが設定されます。通常、ローカル変数は、それを宣言したブロックまたは関数内にのみ存在します。

function() {
  var a = 1;
  console.log(a); // works
}    
console.log(a); // fails

ローカル変数にアクセスしようとすると、ほとんどの言語では現在のスコープ内でその変数を検索し、次に親スコープを経由してルート スコープに到達するまで検索します。

var a = 1;
function() {
  console.log(a); // works
}    
console.log(a); // works

ブロックまたは関数が終了すると、そのローカル変数は不要になり、通常はメモリから消去されます。

これが、私たちが通常期待する動作です。

クロージャは永続的なローカル変数スコープである

クロージャは、コード実行がそのブロックから移動した後でもローカル変数を保持する永続スコープです。クロージャをサポートする言語 (JavaScript、Swift、Ruby など) では、そのブロックまたは関数への参照をどこかに保持しておけば、変数が宣言されたブロックの実行が終了した後でも、スコープ (その親スコープを含む) への参照を保持できます。

スコープ オブジェクトとそのすべてのローカル変数は関数に関連付けられており、その関数が存続する限り存続します。

これにより、関数の移植性が実現します。関数が最初に定義されたときにスコープ内にあった変数は、後で関数を呼び出したときにも、まったく異なるコンテキストで関数を呼び出した場合であっても、引き続きスコープ内にあることが期待できます。

例えば

この点を説明する、JavaScript での非常に簡単な例を次に示します。

outer = function() {
  var a = 1;
  var inner = function() {
    console.log(a);
  }
  return inner; // this returns a function
}

var fnc = outer(); // execute outer to get inner 
fnc();

ここでは関数内に関数を定義しています。内部関数は、 を含むすべての外部関数のローカル変数にアクセスできますa。変数はa内部関数のスコープ内にあります。

通常、関数が終了すると、そのローカル変数はすべて消去されます。ただし、内部関数を返して、関数が終了したfnc後も存続するように変数に割り当てると、関数が定義されたときにスコープ内にあったすべての変数も存続します。変数は閉じられ、クロージャ内にあります。outerinnera

変数はaに対して完全にプライベートであることに注意してくださいfnc。これは、JavaScript などの関数型プログラミング言語でプライベート変数を作成する方法です。

ご想像のとおり、fnc()を呼び出すと の値a「1」が出力されます。

クロージャのない言語では、a関数の終了時に変数はガベージ コレクションされ、破棄されます。fnc を呼び出すと、変数が存在しなくなるouterためエラーが発生します。a

aJavaScript では、関数が最初に宣言されたときに変数スコープが作成され、関数が存在する限り存続するため、変数は存続します。

aは のスコープに属しますouter。 のスコープには、innerのスコープへの親ポインターがありますouterfncは を指す変数ですinner。は、persistes が存続するa限り存続しますfncaはクロージャ内にあります。

さらに読む(視聴)

私が作ったYouTube動画このコードをいくつかの実用的な使用例とともに見てみましょう。

おすすめ記事