【Amazon】人気の商品が日替わりで登場!
毎日お得なタイムセール!商品をみる

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

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

JavaScriptの学習におすすめ書籍
1冊ですべて身につくJavaScript入門講座
総合評価
( 5 )
メリット
  • 誰でも分かるように嚙み砕いて説明してくれる
  • アニメーションの知識が深く学べる
  • 1つのWebサイトを作りながら学べる
楽天ブックス
¥2,794 (2024/04/14 02:03時点 | 楽天市場調べ)
先輩くん

Amazon Kindle Unlimitedに登録すると、月額980円で読み放題だからオススメだよ!

後輩ちゃん

初回30日間は無料だから、まだ登録したことのない人はぜひ試してみてね!

全プログラマー必見!
変数名/関数名にもう悩まない!
リーダブルコード
総合評価
( 5 )
メリット
  • 美しいコードが書けるが自然と書けるようになる
  • 他の開発者が理解しやすいコードになる
著:Dustin Boswell, 著:Trevor Foucher, 解説:須藤 功平, 翻訳:角 征典
¥2,640 (2023/07/23 02:48時点 | Amazon調べ)
目次

クロージャとは?

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

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

プライベート変数の生成

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

例えば、関数が呼び出されると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アクセスランキング にほんブログ村 FC2 Blog Ranking

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次