JavaScript

【JavaScript】クロージャについて理解しよう

本記事では、JavaScriptの登竜門と呼ばれているクロージャについてサンプルコードを用いて分かりやすく解説しています。

JavaScriptの学習におすすめ参考書
改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用まで

参考書が苦手な人はUdemyの動画がおすすめ
ガチで学びたい人のためのWEB開発徹底実践(フロントエンド編)

動画情報
作成者CodeMafia
学習時間19.5時間
受講者数28,547人
レビュー (5,025件)
動画の詳細はこちら

クロージャとは?

クロージャとは、スコープ内に宣言された変数を関数が使用している状態のことを指します。

言葉だけだと何を言いたいのかサッパリわからないと思うので、とりあえずスコープ内の変数を関数が使用ことと頭の片隅に覚えて、実際にクロージャーを使うとどのようなことができるようになるのかサンプルコードを用いて解説していきます。

プライベート変数の生成

クロージャを使うとできることの一つ目は、値を保持し続けられるプライベート変数を作成することができます。プライベート変数とは外部から参照することができない変数のことを指します。

例えば、関数が呼び出されると1ずつカウントされていく処理を作成する場合、クロージャを利用しないと以下のような処理になります。

function incrementFunc() {
  let val = 0;
  val++;
  console.log(val);
}

for (let i = 0; i < 10; i++) {
  incrementFunc();
}

この処理は一見問題なく実行されそうですが、コンソールに出力される値は1のみです。これは何故かというと、関数内で宣言された変数はその関数が再度呼び出されると初期値の0を代入しリセットするからです。

では、変数を関数内ではなく関数外に設定すれば良いのでは?と思いますが、この場合コンソールに出力される値は1〜10で問題ありませんが、関数外に設定される変数はグローバル変数のためどこからで参照・更新することができてしまいます。

このように、プライベート変数に値を保持し続けたい時にクロージャを使用します。クロージャを使った場合の記述は以下の通りです。

function sampleFunc() {
  let val = 0;
  function increment() {
    val++;
    console.log(val);
  }
  return increment;
}

const increment = sampleFunc();
for (let i = 0; i < 10; i++) {
  increment();
}

ここで重要となるポイントは「変数を宣言する場所」「return increment」の2つです。別々に解説していきます。

変数を宣言する場所

1つ目の注目ポイントは、変数を宣言する場所です。今回変数を宣言した場所は一番外側の関数sampleFunc()内です。

sampleFunc()内に変数を設定することでその変数はその関数内でしか使えない、つまりプライベート変数になります。increment関数はsampleFunc関数内にあるので、変数を参照することができます。

function sampleFunc() {
  let val = 0; // -> OK
  function increment() {
    let val = 0 // -> NG
    val++; // -> 参照可能!
    console.log(val);
  }
  return increment;
}

returnで関数を返す

2つ目の注目ポイントは、returnで関数を返すことです。このreturnで変数を返してあげることで、sampleFunc関数が呼ばれてもincrement関数が実行されるようになります。

ここで1つ前の変数だけをincrement関数外に宣言した意味が分かります。

returnでincrement関数を返却すると、sampleFunc関数が呼ばれても処理が実行されるのはincrement関数のみ = increment関数外で宣言された変数は関数が実行されるたびに初期化されない。という仕組みになります。

function sampleFunc() {
  let val = 0; // -> 最初に宣言されて以降、処理は実行されない
  function increment() { // -> sampleFunc関数が呼び出されたらこの関数だけが実行される
    val++;
    console.log(val);
  }
  return increment; // -> increment関数を返却する
}

ブログランキング・にほんブログ村へ PVアクセスランキング にほんブログ村