カリー化について質問したところ、クロージャについて言及されました。クロージャとは何ですか? カリー化とどのように関係していますか?
ベストアンサー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
後も存続するように変数に割り当てると、関数が定義されたときにスコープ内にあったすべての変数も存続します。変数は閉じられ、クロージャ内にあります。outer
inner
a
変数はa
に対して完全にプライベートであることに注意してくださいfnc
。これは、JavaScript などの関数型プログラミング言語でプライベート変数を作成する方法です。
ご想像のとおり、fnc()
を呼び出すと の値a
「1」が出力されます。
クロージャのない言語では、a
関数の終了時に変数はガベージ コレクションされ、破棄されます。fnc を呼び出すと、変数が存在しなくなるouter
ためエラーが発生します。a
a
JavaScript では、関数が最初に宣言されたときに変数スコープが作成され、関数が存在する限り存続するため、変数は存続します。
a
は のスコープに属しますouter
。 のスコープには、inner
のスコープへの親ポインターがありますouter
。fnc
は を指す変数ですinner
。は、persistes が存続するa
限り存続しますfnc
。a
はクロージャ内にあります。
さらに読む(視聴)
私が作ったYouTube動画このコードをいくつかの実用的な使用例とともに見てみましょう。