英文学生の日常

業務日誌.tomo

業務で感じたことをひたすら綴る

2020-5-22

 

 

  • 静的スコープ: ある変数がどの値を参照するかは静的に決まる
  • メモリ管理の仕組み: 参照されなくなったデータはガベージコレクションにより解放される

 

クロージャーとはこの2つの仕組みを利用して、関数内から特定の変数を参照し続けることで関数が状態を持てる仕組みのことを言います。

最初にクロージャーの例として紹介したcreateCounter関数の例を改めて見てみましょう。

 

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

つまり次のような参照の関係がmyCounter変数とcount変数の間にはあることがわかります。

  • myCounter変数はcreateCounter関数の返り値であるincrement関数を参照している
  • myCounter変数はincrement関数を経由してcount変数を参照している
  • myCounter変数を実行した後もcount変数への参照は保たれている

myCounter -> increment -> count

count変数を参照するものがいるため、count変数は自動的に解放されません。 そのためcount変数の値は保持され続け、myCounter変数を実行するたびに1ずつ大きくなっていきます。

このようにcount変数が自動解放されずに保持できているのは「increment関数内から外側のcreateCounter関数スコープにあるcount変数を参照している」ためです。 このような性質のことをクロージャ(関数閉包)と呼びます。クロージャーは「静的スコープ」と「参照され続けている変数のデータが保持される」という2つの性質によって成り立っています。

クロージャーは、変数が参照する値が静的に決まる静的スコープという性質とデータは参照されていれば保持されるという2つの性質によって成り立っています。