【js】クロージャ
クロージャとは、ローカル変数を参照している関数内関数のことです。
なんのこっちゃわからないので、次のコードを見てください。
function countPoint(init) { let point = init; return () => { return ++point; } } let myCounter = countPoint(1); console.log(myCounter()); // 2 console.log(myCounter()); // 3 console.log(myCounter()); // 4 console.log(myCounter()); // 5 console.log(myCounter()); // 6
countPoint関数は戻り値は数値ではなく、数値をインクリメントするアロー関数を返しています。
引数や戻り値が関数である関数のことを高階関数と呼ぶのでした。
このように関数が戻り値として返されて起こることがクロージャの仕組みになります。
通常関数の中で使われたローカル変数(ここでいう変数point)は関数の処理が終了した時点で破棄されるはずです。
しかし、countPoint関数から返されたアロー関数がローカル変数のpointを参照し続けているので、
countPoint関数終了後もローカル変数pointは保持され続けるのです。
スコープチェーンで考えてみると、
- アロー関数を表すCallオブジェクト
- countPoint関数のCallオブジェクト
- グローバルオブジェクト
というスコープチェーンがアロー関数が有効である間は保持されるのです。
別の例を見てみましょう。
function countPoint(init) { let point = init; return () => { return ++point; } } let myCounter1 = countPoint(1); let myCounter2 = countPoint(100); console.log(myCounter1()); // 2 console.log(myCounter2()); // 101 console.log(myCounter1()); // 3 console.log(myCounter2()); // 102
ここでわかるように、呼び出しごとに生成されたCallオブジェクトは別物なのです。
つまり、myCounter1とmyCounter2のCallオブジェクトは別物ですし、
そのCallオブジェクトに属するローカル変数pointもそれぞれ別物なのです。
クロージャとはに付け加えると、一種の記憶域を提供する仕組みでもあると言えます。
まとめ
クロージャとは、
- ローカル変数を参照している関数内関数のこと
- 一種の記憶域を提供する仕組みでもある