クロージャ くろーじゃ
クロージャとは
クロージャ(Closure)とは、関数がその関数が定義されたスコープ(変数の有効範囲)の変数を、スコープを抜け出した後も参照し続けることができる仕組みのことです。平たく言うと、「関数が自分の”生まれ故郷”の変数を記憶している状態」です。
通常、関数の実行が終わると、その中で使われていた変数はメモリから消えてしまいます。しかしクロージャを使うと、内側の関数が外側の関数の変数を”閉じ込めて(close over)“保持し続けることができます。この「閉じ込める」という動作が名前の由来です。
クロージャは JavaScript・Python・Ruby・Swift など多くのモダンな言語でサポートされており、状態の保持・プライベート変数の実現・コールバック関数の実装など、実務でも非常に頻繁に使われる重要な概念です。
クロージャの仕組みと構造
クロージャが成立するには、次の3つの要素が揃う必要があります。
| 要素 | 説明 | 例(JavaScript) |
|---|---|---|
| 外側の関数 | 変数を持つ関数 | function outer() |
| 内側の関数 | 外側の変数を参照する関数 | function inner() |
| 変数のキャプチャ | 外側の変数を内側の関数が記憶している状態 | outer が終了しても count が残る |
以下のコードで動きを確認できます(JavaScript):
function makeCounter() {
let count = 0; // 外側の変数
return function() { // 内側の関数(これがクロージャ)
count++;
return count;
};
}
const counter = makeCounter();
console.log(counter()); // → 1
console.log(counter()); // → 2
console.log(counter()); // → 3
makeCounter() の実行が終わっても、返された内側の関数は count を覚え続けます。counter を何度呼んでも count は加算され続けます。これがクロージャです。
語呂合わせで覚えよう
「クロージャ=クローゼットに変数を閉まっておく関数」
クローゼット(closet)の語感に近いですね。関数がクローゼットの中に変数をしまい込んで、外から見えないけれど自分だけはいつでも取り出せる、というイメージです。
クロージャが活躍する場面
【よく使われるパターン】
1. カウンターや状態の保持
└ 変数を外に露出せずに内部でだけ管理したいとき
2. プライベート変数の擬似実現
└ JavaScriptなど「クラスの非公開変数」が難しい言語で代替
3. コールバック・イベントハンドラ
└ ボタンを押したときに「どのIDのデータか」を記憶しておく
4. 関数ファクトリ(関数を生成する関数)
└ 「5倍にする関数」「10倍にする関数」を動的に作る
歴史と背景
- 1960年代 — クロージャの概念はLISP言語の研究から生まれた。関数型プログラミングの基礎理論として登場
- 1975年 — Schemeがクロージャを言語仕様として正式に採用。「レキシカルスコープ(静的スコープ)」と組み合わせて普及
- 1990年代 — 関数型プログラミング言語(Haskell・ML系)がクロージャを活用。一方、C言語・Javaなどの主流言語では非対応だったため、一般には難解な概念とみなされていた
- 2000年代 — JavaScriptがWebの主役になると、イベント処理やAjax通信でクロージャが必須の知識に。「JavaScriptを理解するにはクロージャを理解せよ」と言われるほど重要な概念になる
- 2010年代以降 — Python・Ruby・Swift・Kotlin・Rustなどほぼすべてのモダン言語がクロージャをサポート。プログラミング教育でも必修トピックとして定着
スコープとの関係・関連概念の比較
クロージャを理解するうえで、スコープ(変数の有効範囲) の概念は切り離せません。
クロージャと似た概念の比較
| 概念 | 説明 | クロージャとの違い |
|---|---|---|
| スコープ | 変数が有効な範囲 | クロージャはスコープを”またいで”変数を保持する仕組み |
| レキシカルスコープ | 変数のスコープがコードを書いた位置で決まること | クロージャが成立するための前提条件 |
| コールバック関数 | 別の関数に渡して後で呼び出す関数 | コールバックがクロージャになることが多い |
| 高階関数 | 関数を引数に取ったり返したりする関数 | クロージャは高階関数と組み合わせて使われる |
| クラス(OOP) | データと操作をまとめる仕組み | クロージャはクラスなしで「状態+操作」を実現できる |
Python でのクロージャ例
def make_multiplier(n):
def multiplier(x): # n をキャプチャしている
return x * n
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # → 10
print(triple(5)) # → 15
n という変数が make_multiplier を抜けた後も multiplier 関数の中に保持されています。double と triple はそれぞれ異なる n を記憶した別々のクロージャです。
関連用語
- スコープ — 変数が参照できる有効範囲のこと。クロージャを理解するための前提知識
- レキシカルスコープ — 変数のスコープがコードの書かれた位置によって静的に決まる仕組み
- 高階関数 — 関数を引数として受け取ったり、関数を返したりする関数
- コールバック関数 — 別の関数に引数として渡して後で実行される関数。クロージャと組み合わせて多用される
- ガベージコレクション — 不要になったメモリを自動回収する仕組み。クロージャが変数を保持するとGCの対象外になる
- 関数型プログラミング — 関数を主役にするプログラミングスタイル。クロージャはその中核的概念
- イベントハンドラ — ボタンクリックなどのイベント発生時に呼ばれる関数。クロージャとして実装されることが多い