FIG-032

クロージャ — 関数が変数を抱えたまま外へ出る

ブラウザ 2026.06.22 公開 読了 約10分

関数の中で作った変数は、ふつう関数を抜けた瞬間に消えます。ところがJavaScriptには、関数が「自分が生まれた場所にあった変数」を抱えたまま外に出ていける仕組みがあります。これがクロージャ(closure)です。関数と、その関数が見えていた変数たちを、ひとまとめに包んで持ち運ぶ —— だから「閉じ込める(close)」と呼ばれます。

言葉だけだとピンと来ないので、下の図1でカウンター工場を動かしてみてください。「新しいカウンターを作る」を押すたびに、makeCounter()自分専用の count を1つ抱えたカウンターを作って返します。それぞれの +1 を押すと、他のカウンターには影響せず、そのカウンターの数字だけが増えます。

function makeCounter() {
  let count = 0; // ← この変数が包まれる
  return () => ++count;
}
ボタンを押すと、自分専用の count を抱えたカウンターがここに並びます
まだカウンターはありません
図1 — 同じ工場から作っても、各カウンターは独立した count を持つ

なぜ count は消えないのか

ふつうに考えれば、makeCounter()return で終わった時点で、その中の count は役目を終えて消えるはずです。でも、返ってきた関数は中で count を使い続けています。「まだ使う人がいる変数」は、JavaScriptが消さずに生かし続ける —— これがクロージャの正体です。関数が外へ出るとき、自分が見えていた変数の部屋(スコープ)を一緒に持って出ていくイメージです。

図1で複数のカウンターを作ると、それぞれが別々の数字を覚えていたのは、makeCounter() を呼ぶたびに新しい count の部屋がもう1つ作られるからです。カウンターAとカウンターBは、別々の部屋を抱えた別々の関数。だから干渉しません。この性質を使うと、外から直接いじれない「関数の中だけの秘密の状態」を持たせられます。Reactの useState やイベントハンドラ、モジュールのプライベート変数など、現代のJSはクロージャだらけです。

用語ミニ辞書
クロージャ
関数と、その関数が定義時に見えていた変数(環境)をひとまとめにしたもの。
スコープ
変数が見える範囲。関数の中で作った変数は、原則その関数の中だけで見える。
レキシカルスコープ
「どこで実行されたか」ではなく「どこに書かれたか」で見える変数が決まる仕組み。
カプセル化
状態を外から直接触れないように包むこと。クロージャはその手段の1つ。

まとめ

クロージャは「関数が、生まれた場所の変数を抱えたまま外へ出ていける」仕組みです。だから関数が終わったあとも変数は生き残り、呼ぶたびに新しい部屋が作られるので、各関数は独立した状態を持てます。図1でカウンターを増やし、片方だけ何度も押してみてください。互いに影響しない数字こそが、クロージャが状態を閉じ込めている証拠です。