🤐

クロージャって何のためにあるん?(JavaScript)

2022/12/17に公開

記事の目的

ふと「そうえいばクロージャって何のために存在するんだっけ?」と思ったので、備忘録がてら簡単にまとめました。
そのうえで、私と同じようにクロージャの必要性がよくわからない人の一助になれればと思い、記事にしました。

この記事で得られること

  • クロージャってなんのためにあるん?を解決できるかも
  • クロージャって何?を少し解決できるかも

結論

クロージャの最大のメリットは、グローバルの汚染を防止し、コードの保守性を高めること。

クロージャとは

関数内で特定の変数を参照し続けることで、関数が状態を持てる仕組みのことです。
JavaScriptはメモリ解放にガベージコレクションを採用しているため、関数内で変数を参照し続ける限りはメモリの状態を保持します。
そのため、変数のデータが初期化されることなく残り続け、あたかも状態を保持しているかのように振る舞います。

const createCounter = () => {
    let count = 0;
    return function increment() {
        // `increment`関数は`createCounter`関数のスコープに定義された`変数`count`を参照している
        count = count + 1;
        return count;
    };
};

// createCounter()の実行結果は、内側で定義されていた`increment`関数
const myCounter = createCounter();
// myCounter関数の実行結果は`count`の評価結果
console.log(myCounter()); // => 1
console.log(myCounter()); // => 2

クロージャは新しい関数を定義する

また、クロージャ関数は実行するたびに、新たな関数が定義されます。
そのため、クロージャ関数を異なる変数に代入した際は、それぞれ異なる状態(データ)を保持します。
関数を製造する工場のような働きを持つことから、このことは、関数ファクトリともよばれるらしいです。

const createCounter = () => {
    let count = 0;
    return function increment() {
        // 変数`count`を参照し続けている
        count = count + 1;
        return count;
    };
};
// countUpとnewCountUpはそれぞれ別のincrement関数(内側にあるのも別のcount変数)
const countUp = createCounter();
const newCountUp = createCounter();
// 参照してる関数(オブジェクト)は別であるため===は一致しない
console.log(countUp === newCountUp);// false
// それぞれの状態も別となる
console.log(countUp()); // => 1
console.log(newCountUp()); // => 1

クロージャを使って何が嬉しいのか

本表題の1つの答えとしては以下のとおりです。

  • グローバル環境を汚さないで済む

クロージャを使用するとグローバル汚染を防ぐことができます。つまり、保守性の高いプログラムを書くこといができるということです。
クロージャの特性を使用することで静的スコープに閉じられた変数を参照できるため、無駄なグローバル変数を定義して、グローバル環境を汚さずに済みます。

まとめ

  • クロージャとは、関数内で特定の変数を参照し続けることで、関数が状態を持てる仕組みのこと。
  • クロージャは呼び出す度に、新たな関数を定義する関数ファクトリ。
  • クロージャを使用することで、グローバル汚染を防ぐことができ、保守性が高まる。

以上です。
間違い・補足等ありましたら、コメントで教えてもらえたら嬉しいです。
ありがとうございました。

参考

関数とスコープ
クロージャ - JavaScript | MDN
真面目に JavaScript のクロージャを解説する - プログラムを自動生成したい

Discussion