こんにちは。フロントエンドの現場で長年コードと向き合っていると、「JavaScriptって、時々魔法みたいな動きをするな」と感じることがあります。その最たるものが、今回お話しする「クロージャ」という概念です。
名前こそ少し難しそうですが、実は私たちの日常にも溢れている「ある仕組み」に似ています。今日は、この不思議で強力なテクニックの正体を、一緒に紐解いていきましょう。
—
1. クロージャって、結局なに?
一言で言うと、クロージャは「関数が、生まれた時の環境をずっと覚えている魔法のバックパック」です。
普通、関数の中で作った変数は、その関数が終わった瞬間に消えてしまいますよね。例えば、料理を作っている最中にだけ使うボウルや計量カップのようなものです。料理(関数)が終われば、それらは片付けられてしまいます。
でも、クロージャを使うと、「料理が終わった後も、特定の道具をずっと手元に残しておける」のです。
身近な例:お買い物券のシステム
想像してみてください。お店で「100円引きクーポン」をもらったとします。このクーポンは、あなたがお店を出た後も「あなたは100円割引できる権利を持っている」という記憶を保持していますよね。
JavaScriptのクロージャもこれと全く同じです。関数が「外側の変数」をしっかりと握りしめて離さない。この仕組みのおかげで、関数を実行した後でも、その時の情報を使い続けることができるのです。
—
2. コードで見てみよう:バックパックの中身
実際に、カウンター(数え上げ)を作るコードで確認してみましょう。
function createCounter() {
let count = 0; // この変数は、関数の外からは触れない「秘密の金庫」の中にあるイメージ
return function() {
count++; // 外側の変数を書き換える
console.log(`現在のカウントは: ${count} です`);
};
}
// カウンターを起動!
const myCounter = createCounter();
myCounter(); // 1
myCounter(); // 2
myCounter(); // 3
ここで不思議なことが起きています。`createCounter`関数は実行が終わったはずなのに、なぜ`count`という変数は消えずにカウントアップされ続けているのでしょうか?
これがクロージャの力です。内側の関数が「外側の`count`という変数を将来使うかもしれないから、私のバックパックに入れておこう!」と判断し、メモリ上に保持し続けているのです。
—
3. なぜメモリが解放されないの?(ガベージコレクションの話)
ここで、「ずっと保持していたら、メモリがパンクしないの?」という鋭い疑問が浮かぶかもしれません。
JavaScriptには、使わなくなったゴミを自動で片付ける「ガベージコレクション(GC)」というお掃除係がいます。このお掃除係は、基本的に「どこからも参照されていない変数」を見つけると即座にゴミ箱へ捨てます。
しかし、クロージャが発生している場合、お掃除係がやってきても、内側の関数が「この変数はまだ使ってるよ!」と主張しているため、お掃除係は手を出せません。
- メリット: 状態を保持し続けられるため、プライベートな変数を作れる。
- 注意点: 使い終わったはずの大きなデータまで握りしめ続けると、メモリを圧迫してしまう。
つまり、クロージャは「便利だけど、お掃除係の邪魔をしてしまうこともある強力な仕組み」なのです。
—
4. 初学者がつまずきやすいポイント
よくあるのが、ループ処理の中でクロージャを使ってしまうケースです。
// 注意:var を使うと、変数が共有されてしまい、意図しない挙動になることがあります
for (var i = 1; i <= 3; i++) {
setTimeout(function() {
console.log(i); // 全部「4」になってしまう!
}, 1000);
}
これは、全ての関数が同じ`i`という箱を参照してしまっているからです。現代のJavaScriptでは、`let`を使うことで、ループのたびに新しい箱(スコープ)が作られるため、この問題は解決します。
「`let`を使っておけば大丈夫!」と覚えておくだけで、クロージャの沼にはまるリスクはぐっと減りますよ。
—
最後に:怖がらなくて大丈夫
クロージャは、最初はとっつきにくいかもしれません。でも、「関数が自分を囲む環境を大切に抱えているだけなんだ」とイメージしてみてください。
今のフロントエンド開発では、Reactのフック(Hooks)などで、このクロージャの仕組みが裏側でフル活用されています。つまり、あなたがクロージャを理解することは、モダンなWeb開発の心臓部を理解することに他なりません。
焦る必要はありません。まずは「関数って、外側の情報を持ち歩けるんだな」という感覚を大切に、色々なコードを書いて遊んでみてくださいね。
皆さんのコーディングライフが、少しでも楽しく、軽やかなものになりますように!また何か詰まったら、いつでも聞きに来てくださいね。

コメント