【くろーじゃ】

クロージャ とは?

最終更新:
💡 関数が、生まれた場所の変数に手を伸ばせる

関数と、その関数が定義された場所の変数を参照する環境の組み合わせ。外側の関数の実行が終わっても、その変数を使える。JavaScriptでは関数を作るときに形成される。

📌 このページのポイント
クロージャ:関数と変数の環境makeCounter()で作る変数 count最初は 0返す関数countを増やす外側の実行が終わっても関数は、このcountにアクセスできる同じ関数を呼ぶ1 → 2 → 3同じcountを更新もう一度作る別のcountは 0新しい環境になる
JavaScriptの例。値の固定コピーではなく、関数が変数を参照する環境を持ちます。
ひよこ ひよこ
クロージャって、特別な種類の関数なの?
ペンギン先生 ペンギン先生
JavaScriptでは、関数を作るときに形成されるよ。関数本体と、定義された場所の変数を参照する環境を合わせたものなんだ。外側の関数が実行を終えても、そこにあった変数を後で使えるのが分かりやすい例だね。
ひよこ ひよこ
カウンターにすると、どうなるの?
ペンギン先生 ペンギン先生
makeCounterの中でlet count = 0を用意し、countを1増やして返す関数を戻すとするよ。その戻り値をcounterとして呼ぶと、counter()は1、次は2になる。呼ぶたびに同じcountへアクセスできるから、数を覚えていられるんだ。
ひよこ ひよこ
もう一つカウンターを作ったら、数は一緒?
ペンギン先生 ペンギン先生
makeCounterをもう一度呼んで作れば、別の環境のcountを使うよ。一方で、1回の呼び出しから複数の関数を返すと、それらが同じ変数を共有することもある。関数が何個あるかだけで、変数が別々とは決まらないんだ。
ひよこ ひよこ
変数のコピーを保存しているわけではない?
ペンギン先生 ペンギン先生
JavaScriptでは、変数を参照する環境を保持するよ。だから共有する変数を書き換えると、後で関数を呼んだときの結果にも反映される。作った瞬間の値を写真のように固定する、と考えると間違えやすいんだ。
ひよこ ひよこ
ループでletを使うと、共有を避けられる?
ペンギン先生 ペンギン先生
例えばfor (let i = 0; i < 3; i++)のiは、反復ごとの環境で扱われるよ。varで共有するiとは挙動が違う。ただしループの外で宣言した変数や同じオブジェクトを使えば、それは共有される。letならどんな共有もなくなるわけではないんだ。
ペンギン
まとめ:ざっくりこれだけ覚えればOK!
「クロージャ」って出てきたら「作られた場所の変数を使い続けられる関数」と思えばだいたいOK!
📖 おまけ:英語の意味
「Closure」 = 閉包
💬 関数が外側の変数を取り込んだ環境と組になることを表す呼び名だよ。「値をその時点のまま閉じ込める」という意味ではないんだ。

参考資料

← 用語集にもどる