【JavaScript入門】クロージャ

 JavaScript の「クロージャ(closure)」は、関数内で定義した関数が、その外側のスコープにある変数を 取り込んで 参照または操作できる仕組みを指します。クロージャによって、外側の関数が終了した後も、内部関数が外部スコープの変数を保持し続けることが可能です。これにより、「関数が状態を保持する」ような設計ができ、さまざまな応用が可能になります。以下ではクロージャの基本的な例や、実践的な利用例を紹介します。

1.クロージャの基本

 外側の関数(スコープ)にある変数や引数を、内側の関数が取り込んで利用できるという性質がクロージャです。内側の関数を外側から返すことで、外側のスコープが終わっても値を保持し続けます。

【myClosureExample.html】

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>myClosureExample.html</title>
</head>
<body>
  <h1>クロージャのサンプル</h1>
  <p>ブラウザの開発者ツールを開き、コンソールに注目してください。</p>

  <script>
    // 1. 基本的な例
    function getFunc() {
      // 外側関数の変数
      const name = 'チョコレートパフェ';

      // 内側関数 (この中で外側の変数を使う)
      function innerFunc() {
        // innerFunc内で宣言した変数
        const price = 850;
        console.log(`${name}:${price}円`);
      }

      // 内側関数を返す → これがクロージャ
      return innerFunc;
    }

    // クロージャを取得
    const func = getFunc();
    // func() を実行すると、すでに外側関数 getFunc() は終わっているが、
    // 取り込んだ変数 name を保持し、アクセスできる
    func();

    // 2. クロージャの応用例:呼び出し回数をカウント
    function createCounter(label) {
      let count = 0;

      return function() {
        count++;
        return `${label}は ${count}回呼び出されました`;
      };
    }

    const counterA = createCounter('A');
    const counterB = createCounter('B');

    console.log(counterA()); // Aは 1回呼び出されました
    console.log(counterB()); // Bは 1回呼び出されました
    console.log(counterA()); // Aは 2回呼び出されました
    console.log(counterB()); // Bは 2回呼び出されました
    console.log(counterB()); // Bは 3回呼び出されました
  </script>
</body>
</html>

デバックコンソールの出力

チョコレートパフェ:850円
Aは 1回呼び出されました
Bは 1回呼び出されました
Aは 2回呼び出されました
Bは 2回呼び出されました
Bは 3回呼び出されました

解説

  • getFunc() は内部に name を定義しており、さらに innerFunc() という関数を返します。この innerFunc() が「クロージャ」と呼ばれるもので、name(外側の変数)を参照しているため、getFunc() を呼び出した後でも name を保持し続けます。
  • createCounter() ではカウント用の count 変数が閉じ込められ、返された内部関数でカウントを操作していきます。counterAcounterB はそれぞれ独立したスコープを保持しているため、カウントが別々に記録されます。

2.クロージャのメリットと注意点

  • メリット
    ・関数が終了した後も、外側の関数スコープで定義した変数を保持・操作できる。
    ・データのカプセル化により、特定の関数からしか値を変更できないようにするなど、情報隠蔽的な設計が可能。
  • 注意点
    ・不要なクロージャを多用するとメモリを無駄に消費する場合がある。
    ・スコープが複雑になると、変数のライフタイムが把握しづらくなる。

まとめ

  • クロージャ とは、関数が外部スコープの変数を取り込み、関数が呼び出し元のスコープから独立してもその変数を参照・変更できる仕組み。
  • 複数のクロージャが同じ外部スコープを共有していると、それぞれが同じ変数を変更し合うことが可能になる。
  • 呼び出し回数をカウントしたり、モジュール的に状態を隠蔽したりと、JavaScript ならではの設計パターンに広く活用される。

 クロージャを理解することで、JavaScript のスコープチェーンや関数オブジェクトの動きがより鮮明になり、柔軟で強力なプログラミングが可能になります。