カテゴリ: JavaScript 更新日: 2026/05/01

JavaScriptのクロージャーとは?仕組みと実践例をやさしく解説

JavaScriptのクロージャーとは?仕組みと実践例をやさしく解説
JavaScriptのクロージャーとは?仕組みと実践例をやさしく解説

先生と生徒の会話形式で理解しよう

生徒

「先生、JavaScriptのクロージャーって聞いたことはあるけど、いまいち何かわからないです。教えてください!」

先生

「クロージャーは少し難しい言葉ですが、簡単にいうと『関数が自分の外側の変数を覚えて使い続ける仕組み』のことです。」

生徒

「関数が変数を覚える?どういうことですか?」

先生

「例えば、お菓子の箱を開けて中身を見て、その箱を閉じても、中身のことを忘れないようなイメージですね。関数は箱で、中の変数が中身です。」

生徒

「なるほど。クロージャーはプログラムのどんなときに使うんですか?」

先生

「よく使うのは、変数を隠して安全に使いたいときや、関数の中に状態を持たせたいときです。実践的な例もあとで紹介しますね。」

1. クロージャーとは?

1. クロージャーとは?
1. クロージャーとは?

クロージャーとは、JavaScriptで関数が作られたときの周囲の環境(変数の状態)を覚え続ける仕組みのことです。 一度実行が終わった関数でも、その中で参照していた変数を、あとから呼び出された関数が使い続けられる点が特徴です。

通常であれば、関数の処理が終わると中の変数は役目を終えます。 しかしクロージャーが関係すると、「もう終わったはずの関数の変数」が、別の関数の中で生き続けます。 この少し不思議な動きが、クロージャーを難しく感じさせる理由でもあります。

プログラミング未経験の方は、「関数が自分専用のメモを持っている」と考えるとイメージしやすいでしょう。 箱の中にメモを入れておき、その箱を閉じても、あとでまた同じメモを取り出せるような感覚です。


function makeMessage() {
  let message = "こんにちは";
  return function() {
    console.log(message);
  };
}

const showMessage = makeMessage();
showMessage(); // 「こんにちは」と表示される

この例では、makeMessage関数の中で定義されたmessageという変数を、 戻り値の関数が覚えています。 そのため、makeMessageの処理が終わったあとでも、 showMessage()を呼び出すと同じ文字が表示されます。 これがクロージャーの基本的な考え方です。

2. クロージャーの基本的な仕組み

2. クロージャーの基本的な仕組み
2. クロージャーの基本的な仕組み

通常、関数の中で使う変数は、関数の処理が終わると役目を終えて消えていきます。 だから「関数の外からは中の変数を使えない」というのが基本です。

ところがクロージャーが関係すると、関数が終わったあとでも変数が残っているように見える状況が作れます。 正確には、内側の関数が外側の変数を参照している限り、その変数の状態が保たれます。 「外側の変数を、内側の関数がポケットに入れて持ち歩く」ようなイメージを持つと理解しやすいです。

まずは一番よく使われる形として、外側の関数が内側の関数を返す例を見てみましょう。 内側の関数を呼び出すたびに、外側の変数が変化していくのがポイントです。


function outer() {
  let count = 0;
  function inner() {
    count++;
    console.log(count);
  }
  return inner;
}

const counter = outer();
counter(); // 1
counter(); // 2
counter(); // 3

この例では、outer関数の中にあるcountという変数を、inner関数が参照しています。 そのため、outer()の実行が終わっても、innerが残っている限りcountも一緒に残ります。 そしてcounter()を呼ぶたびに、同じcountが更新されていくので、数が1、2、3…と増えていくわけです。

もう少し短い例で、「覚えている」感じを確かめてみます。 たとえば、countの値を表示するだけのメソッドでも、同じ仕組みで状態が保たれます。


function makeCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  };
}

const c = makeCounter();
console.log(c()); // 1
console.log(c()); // 2

このようにクロージャーの基本は、「外側の変数を参照している内側の関数があると、その変数の状態が残る」という点にあります。 まずはこの仕組みが分かると、クロージャーの動きがぐっと読みやすくなります。

3. なぜクロージャーが便利なのか?

3. なぜクロージャーが便利なのか?
3. なぜクロージャーが便利なのか?

クロージャーが便利だと言われる理由は、大きく分けて「変数を守れる」ことと、 「状態を覚えられる」ことにあります。 JavaScriptでアプリやWebページを作っていると、クリック回数や入力の進み具合など、 途中の状態を記録しておきたい場面がよく出てきます。

まず「変数を守れる」というのは、必要以上に外から値をいじれないようにできる、という意味です。 たとえば、カウント用の変数をグローバルに置くと、別の処理がうっかり書き換えてしまうことがあります。 クロージャーを使えば、変数は関数の中に隠れているので、外から直接触れません。

次に「状態を覚えられる」というのは、関数を呼び出すたびに前回の続きから処理できることです。 これにより、毎回ゼロから計算し直すのではなく、前の結果を使って自然に処理をつなげられます。 たとえば、ボタンのクリック回数を数えたり、ログイン回数を記録したりするケースが分かりやすいでしょう。


function createClickCounter() {
  let clicks = 0; // 外から直接触れない
  return function() {
    clicks++;
    console.log("クリック回数: " + clicks);
  };
}

const countClick = createClickCounter();
countClick(); // クリック回数: 1
countClick(); // クリック回数: 2
countClick(); // クリック回数: 3

この例では、clickscreateClickCounterの中にあるため、 外側からclicks = 100のように勝手に変更できません。 それでも、countClick()を呼ぶたびに前回の値を覚えているので、 クリック回数が1、2、3…と増えていきます。

つまりクロージャーは、「値を安全にしまっておき、必要なときだけ使う」ための仕組みです。 小さなサンプルでは地味に見えますが、JavaScriptの開発では意外と出番が多く、 コードを整理したいときに頼りになります。

4. 実践例:カウンターを作ってみよう

4. 実践例:カウンターを作ってみよう
4. 実践例:カウンターを作ってみよう

ここでは、クロージャーの動きを実際に目で確認できる定番の例として、 カウンター(数を数える仕組み)を作ってみます。 数字が増えていく様子を見ることで、「変数を覚えている」という感覚がつかみやすくなります。

ポイントは、カウント用の変数countを関数の外に出さず、 関数の中に閉じ込めている点です。 これにより、外から勝手に値を変更される心配がなくなります。


function createCounter() {
  let count = 0;
  return function() {
    count++;
    return count;
  };
}

const counter1 = createCounter();
console.log(counter1()); // 1
console.log(counter1()); // 2

const counter2 = createCounter();
console.log(counter2()); // 1
console.log(counter2()); // 2

このコードでは、createCounterを呼び出すたびに、 新しいcountを持つ関数が作られます。 そのため、counter1counter2は、 同じカウンターのように見えても、中身はまったく別物です。

counter1()を何回呼んでもcounter2の値には影響せず、 それぞれが自分専用の数字を覚えています。 これが「クロージャーによって状態が保持されている」状態です。

初心者の方は、「関数を作るたびに、専用のメモ帳が一冊ずつ用意される」と考えると分かりやすいでしょう。 カウンターはシンプルですが、クロージャーの本質を理解するにはとても良い練習になります。

5. クロージャーを使うときの注意点

5. クロージャーを使うときの注意点
5. クロージャーを使うときの注意点

クロージャーは便利ですが、使いすぎるとメモリをたくさん使ってしまうことがあります。

また、変数の状態が長く残るので、意図しない動きになることもあります。

ですから、必要なときだけ使うようにしましょう。

6. クロージャーのポイント整理

6. クロージャーのポイント整理
6. クロージャーのポイント整理

ここまで見てきたように、JavaScriptのクロージャーは 「関数が自分の外側にある変数を覚えたまま動き続ける仕組み」です。 一度実行が終わった関数の中の変数でも、別の関数から参照されていれば、 その値は失われずに保持されます。

この仕組みを使うことで、外から直接触れない変数を作れたり、 関数の中に「状態」を持たせたりできます。 グローバル変数をむやみに増やさずに済むため、 プログラム全体が読みやすく、管理しやすくなるのも大きなメリットです。

初心者の方は、「クロージャー=難しい特別な機能」と考えがちですが、 実際は関数と変数の関係を少し深く理解したものにすぎません。 外側の変数を使っている内側の関数があれば、 そこにクロージャーが生まれている、と覚えておくと混乱しにくいでしょう。


function createGreeting() {
  let message = "こんにちは";
  return function(name) {
    console.log(message + "、" + name + "さん");
  };
}

const greet = createGreeting();
greet("太郎");
greet("花子");

この例では、messageという変数を内側の関数が覚えています。 そのため、名前だけを渡すシンプルな呼び出しでも、 同じあいさつ文を何度も使い回せます。 これもクロージャーによって状態が保たれているからこそ実現できる動きです。

まずは「変数を覚えている関数がある」という感覚をつかむことが大切です。 カウンターや簡単なあいさつの例を何度か書いてみると、 クロージャーの考え方が自然と身についていきます。

まとめ

まとめ
まとめ

クロージャーの仕組みを振り返る

ここまでの記事では、JavaScriptのクロージャーについて、基本的な考え方から実践的な使い方までを順番に見てきました。 クロージャーは一見すると難しい言葉ですが、仕組みそのものはとてもシンプルです。 「関数が作られたときの変数の状態を覚え続ける」という特徴を持っていることが、クロージャーの本質だといえます。

通常の関数では、関数の実行が終わると中で使っていた変数は役目を終えます。 しかし、関数の中で別の関数を作り、その関数を外に返すと、内側の関数は外側の変数を覚えたまま動き続けます。 この「覚えている状態」がクロージャーです。

クロージャーが役立つ理由

クロージャーが便利なのは、変数を安全に管理できる点にあります。 グローバル変数のように誰からでも触れる状態ではなく、必要な関数からだけアクセスできるため、 プログラム全体の見通しが良くなります。

また、関数の中に状態を持たせられるため、「前回の結果を覚えて次に活かす」といった処理が自然に書けます。 カウンターの例のように、呼び出すたびに値が変わる仕組みは、クロージャーを使うことでとても簡潔に表現できます。

サンプルで再確認してみよう

ここでもう一度、クロージャーの動きを確認できるシンプルな例を見てみましょう。 この例では、文字列を覚えて表示する関数を作っています。


function createMessage(message) {
  return function() {
    console.log(message);
  };
}

const hello = createMessage("こんにちは");
const thanks = createMessage("ありがとう");

hello();
thanks();

このコードでは、createMessageの中で受け取った文字列が、 返された関数の中で使われ続けています。 それぞれの関数が、自分専用の文字列を覚えている点がクロージャーの特徴です。

クロージャーを使うときの心構え

クロージャーはとても強力な仕組みですが、便利だからといって何でもクロージャーで書くのはおすすめできません。 変数の状態が長く残るため、意図しない動作やメモリの無駄につながることもあります。

「変数を隠したい」「状態を保持したい」といった目的がはっきりしている場面で使うことで、 クロージャーは本来の力を発揮します。 まずは小さな例で慣れてから、実際のアプリケーションに取り入れていくと理解が深まりやすいでしょう。

先生と生徒の振り返り会話

生徒

「最初はクロージャーって難しそうだと思っていましたけど、 関数が変数を覚えている仕組みだと考えると、少しイメージできました。」

先生

「それで大丈夫ですよ。大切なのは、動きをイメージできることです。 完璧に説明できなくても、使いどころが分かれば十分です。」

生徒

「カウンターやメッセージの例を見ると、 同じ関数から別々の状態を持てるのが便利だと感じました。」

先生

「その気づきはとても良いですね。 クロージャーは状態を持つ関数を作れる点が一番の強みです。」

生徒

「これからコードを書くときに、 変数をどこに置くか考えるのが少し楽しくなりそうです。」

先生

「その感覚を大切にしてください。 クロージャーはJavaScriptらしさを理解する大きな一歩になりますよ。」

カテゴリの一覧へ
新着記事
New1
JavaScript
JavaScriptの配列から要素を削除する方法(pop, shift, spliceなど)完全ガイド
New2
JavaScript
JavaScriptで配列を作成する方法!リテラル表記とArrayコンストラクタを比較
New3
TypeScript
TypeScriptのUnion型とMapped Typesの活用法!初心者向け解説
New4
JavaScript
JavaScriptのデータ型の違いを表で比較しよう(一覧解説)
人気記事
No.1
Java&Spring記事人気No1
JavaScript
JavaScriptのインストール方法まとめ!Windows・Mac・Linux別にステップ解説
No.2
Java&Spring記事人気No2
TypeScript
TypeScriptでコメントを書く正しい書き方と使い分け【初心者向けにやさしく解説】
No.3
Java&Spring記事人気No3
TypeScript
TypeScriptの始め方:開発環境の構築手順【初心者向け】
No.4
Java&Spring記事人気No4
JavaScript
JavaScriptでJSONを文字列に変換する方法を初心者向けに解説!JSON.stringifyの使い方ガイド
No.5
Java&Spring記事人気No5
JavaScript
JavaScriptでJSON操作の注意点を徹底解説!初心者でも安全に扱える方法
No.6
Java&Spring記事人気No6
TypeScript
TypeScriptで関数の型を再利用!ParametersとReturnTypeの使い方を初心者向けに徹底解説
No.7
Java&Spring記事人気No7
JavaScript
JavaScriptの配列の一部を切り出す(slice, spliceの使い方)
No.8
Java&Spring記事人気No8
TypeScript
TypeScriptで使える基本の型一覧(string, number, booleanなど)