1. 0 から 3 回数える
  2. 120 から 2 回数える
  3. 1 回だけ数える
  4. 0 回のときは空の配列
  5. 5 回続けて数える
コース一覧
モダンJavaScript:データ処理とコード設計
クロージャで状態を閉じ込める

モダンJavaScript:データ処理とコード設計

配列の map・filter・reduce・sort、クロージャと高階関数、オブジェクトとクラス、エラー設計、正規表現を学ぶ全 36 レッスン(665 分)のコースです。ローカルの作品データを題材に、表示とデータを分け、絞り込み・並び替え・入力検証までを組み立てます。Promise、fetch、API 通信、モジュールは次のコースで扱います。

1
土台をそろえる
01. このコースで育てるもの15分
02. strict mode が先に教えてくれる間違い15分
03. 表示とデータを切り分ける20分
04. 第1章まとめクイズ10分
2
配列をパイプラインで扱う
01. map で形を変える20分
02. filter と find で絞り込む20分
03. reduce でひとつにまとめる20分
04. sort と比較関数20分
05. 分類してまとめる groupBy20分
06. つなげて組み立てる20分
07. つくる 作品一覧の絞り込みと並び替え30分
08. 第2章まとめクイズ10分
3
関数を道具にする
01. クロージャで状態を閉じ込める20分
02. 設定を覚えた関数をつくる20分
03. 関数を返す関数20分
04. 副作用のない関数20分
05. 第3章まとめクイズ10分
4
オブジェクトを扱いきる
01. 分割代入で必要な値だけ取り出す20分
02. スプレッドとレストで組み替える20分
03. keys と values と entries20分
04. ビット演算でフラグをまとめる20分
05. 第4章まとめクイズ10分
5
クラスで型をつくる
01. クラスとインスタンス20分
02. private フィールドとアクセサ20分
03. 継承と super20分
04. 多態と static20分
05. つくる 作品コレクションをクラスにする30分
06. 第5章まとめクイズ10分
6
エラーを設計する
01. try catch finally20分
02. 自分でエラーを投げる20分
03. 失敗を画面に出す25分
04. 第6章まとめクイズ10分
7
正規表現
01. 正規表現のきほん20分
02. 入力を検証する20分
03. 置換とキャプチャ20分
04. 第7章まとめクイズ10分

クロージャで状態を閉じ込める

抱えたまま生き残る count
解説

このレッスンで分かること

  • 関数の中で作った変数が、関数を抜けたあとも生き残る仕組み
  • 同じ工場から作った関数どうしが、別々の状態を持つこと

誰でも書き換えられる場所に置いてしまう

プロフィールサイトのメニューが今開いているかどうかを覚えておきたい、としましょう。素直に書くとこうなります。

JavaScript

let isOpen = false; function toggleMenu() { isOpen = !isOpen; return isOpen; }

動きます。ただし isOpen はファイルのどこからでも書き換えられます。あとから誰かが別の場所で isOpen = false と書けば、メニューは開いたままなのに閉じている扱いになります。切り替えたいのは toggleMenu だけなのに、書き換えられる範囲だけがファイル全体に広がっている、という状態です。

解説

変数を置く場所を決めるときは、「誰が読めるか」より先に「誰が書き換えられるか」を考えます。書き換える人がひとりだけなら、その人の内側に置くのがいちばん壊れにくくなります。

関数の中に置いて、関数ごと返す

書き換えるのが toggleMenu だけなら、isOpen をその外側の関数の中に入れてしまいます。

JavaScript

function createToggle() { let open = false; return function () { open = !open; return open; }; } const toggleMenu = createToggle(); console.log(toggleMenu()); // true console.log(toggleMenu()); // false

createToggle は、呼ばれると let open = false を用意し、open を触る関数を作って返します。返した時点で createToggle の実行は終わりますが、open は消えません。返された関数がまだ open を使うので、JavaScript は残しておきます。この「返された関数が、生まれた場所の変数を連れて出ていく」形をクロージャと呼びます。

大事なのは、open がもうどこからも名前で呼べないことです。値を変える方法は toggleMenu() を呼ぶことだけになりました。値の寿命はそのままに、触れる範囲だけを狭めた、と言い換えられます。

置き場所外から書き換えられるか値の寿命
ファイル直下の letどこからでもできるページを閉じるまで
関数の中の let (返さない)できない関数を抜けた時点で消える
関数の中の let (関数ごと返す)できない返した関数が生きている間

3 行目だけが「消えない」と「触れない」を両立しています。クロージャを使う理由はここに尽きます。

工場を呼ぶたびに、別の箱ができる

createToggle を 2 回呼ぶと、open も 2 つできます。呼び出しのたびに let open = false が新しく実行されるからです。

JavaScript

const toggleMenu = createToggle(); const togglePanel = createToggle(); console.log(toggleMenu()); // true console.log(toggleMenu()); // false console.log(togglePanel()); // true

toggleMenu を 2 回呼んでも togglePanel は影響を受けません。作品カードごとに状態を持ちたいときは、カードの数だけ工場を呼べばよい、ということです。グローバル変数でこれをやろうとすると、カードの数だけ変数名を考えることになります。共有されるのは「作りかた」であって「値」ではありません。

なお、閉じ込めた値はコンソールから覗けません。動きを確かめたいときは、返ってきた関数を呼んだ戻り値をそのまま見ます。今回の課題も、その戻り値で正しさを測ります。

よくある間違い

  • 工場を呼ばずに名前だけ代入する — const toggleMenu = createToggle; と書くと、返ってくるのは工場そのものです。使うのは createToggle() の戻り値のほうだ、と覚えます
  • let を工場の外に出してしまう — 外に出すと 2 つ作っても箱はひとつしかなく、toggleMenu と togglePanel が同じ値を取り合います。宣言は必ず工場の内側に書きます

要件

  1. 関数名は trackViews とし、引数は startCount (数値) と times (数値) の 2 つにする
  2. 関数の中で、カウンタ用の関数を返す関数を定義して使う。数える変数は返した関数の外側に置き、関数の外から触れないようにする
  3. カウンタは呼ばれるたびに 1 増え、増えたあとの値を返す。startCount が 0 なら 1 回目の戻り値は 1 になる
  4. 戻り値は times 個の数値が入った配列にする。times が 0 のときは空の配列を返す

入出力例

trackViews(0, 3) → [1,2,3] trackViews(120, 2) → [121,122] trackViews(7, 1) → [8] trackViews(5, 0) → [] trackViews(100, 5) → [101,102,103,104,105]

ヒント

先に「カウンタを作る関数」を頭の中で分けます。数える変数を用意して、それを 1 増やす関数を返すだけの小さな関数です。

工場の中は let count = startCount と return function () { count = count + 1; return count; } の 2 つでできます。工場を呼んだ戻り値を変数に受け取ってから使います。

呼び出しは for で times 回まわし、戻り値を配列に push します。count は工場の中に置きます。trackViews の直下に書くと、工場を作る意味がなくなります。

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/03/27·更新 2026/08/26

関連レッスン

  • 設定を覚えた関数をつくる

    しきい値や単位のような設定を先に受け取り、その設定を覚えた関数を返すやりかたを学びます。filter や map にそのまま渡せる判定関数を作り分けられるようになります。

  • 関数を返す関数

    複数の変換を 1 本の関数に合成するやりかたを学びます。処理の順番を配列で受け取り、組み立てた関数を map にそのまま渡せるようになります。

  • 副作用のない関数

    同じ引数なら同じ戻り値になり、受け取った値を書き換えない関数の書きかたを学びます。元のデータを守りながら、新しい配列を作って返せるようになります。

  • 第3章まとめクイズ

    クロージャ、設定を覚えた関数、関数の合成、副作用のない関数の 4 本を振り返ります。コードを読んで結果を答える 5 問です。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • 関数処理に名前を付けて再利用できる単位
  • 変数データに名前をつけて参照する仕組み
  • JavaScriptWeb で動的な振る舞いを担う言語
  • 戻り値呼び出し元への返答を表す点線矢印
  • 引数位置引数=順番で渡す。
  • カウンタ数を保持して増減する典型 UI
  • 配列サイズ固定の同型データの集まり
main.js
学習モード
エディタを読み込んでいます

メモ

クロージャで状態を閉じ込める

⌘S で保存