2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

クロージャを使いこなす:JavaScriptにおける状態管理と情報隠蔽の設計戦略

Posted at

概要

JavaScriptにおける関数は、単なる処理のブロックではない。
それは、スコープと状態を「閉じ込める」構造を持つ、一種のオブジェクトである。

この“関数が状態を保持する”という特徴の本質が、**クロージャ(Closure)**だ。
「関数が変数を覚えている」という一言では説明しきれないその挙動を、構造・記憶・責任の設計という視点で再定義する。


対象環境

ES5以降のすべてのJavaScript環境(Node.js / ブラウザ)

クロージャとは何か?

関数が、自身のスコープ外の変数を“保持し続ける”機能

✅ 具体例:

function counter() {
  let count = 0;
  return function () {
    count++;
    return count;
  };
}

const increment = counter();

console.log(increment()); // 1
console.log(increment()); // 2

countcounter の中で定義されたが、返された関数がそれを保持し続けている


なぜクロージャが生まれるのか?

クロージャの発生条件:

  1. 関数がネストされている
  2. 内側の関数が、外側の変数を参照している
  3. 外側の関数が終了しても、内側関数がどこかで参照されている
function outer() {
  let secret = 'inside';
  return function inner() {
    console.log(secret);
  };
}

innersecret を“記憶している”


実務での用途①:状態管理

クロージャを使えば、外部からアクセスできない状態を内部に保持し続けられる

function createStore(initial = 0) {
  let state = initial;
  return {
    get: () => state,
    set: (v) => (state = v),
    reset: () => (state = initial)
  };
}

const store = createStore(10);
store.set(42);
console.log(store.get()); // 42
store.reset();
console.log(store.get()); // 10

state という値は、外部からは直接触れず、メソッド経由でしか操作できない


実務での用途②:関数のカスタマイズ・カリー化

function multiply(factor) {
  return function (value) {
    return value * factor;
  };
}

const double = multiply(2);
console.log(double(10)); // 20

factor を記憶しているので、部分適用された関数を生成できる


実務での用途③:イベントリスナーのスコープ隔離

for (let i = 0; i < 3; i++) {
  setTimeout(function () {
    console.log(i);
  }, 100);
}

→ ES6の let がブロックスコープなので問題ないが、var ではクロージャがなければ正しく動作しなかった。


落とし穴と注意点

❌ メモリリーク

クロージャは「状態を保持し続ける」がゆえに、意図せず変数を解放できないことがある。

function hold() {
  let bigData = new Array(1000000).fill('...');
  return () => bigData;
}
const ref = hold();
// `bigData` は GC 対象外になる

→ ✅ 不要になった関数への参照は明示的に破棄する(nullにするなど)


❌ thisの扱いに注意

function outer() {
  let name = 'toto';
  return function () {
    console.log(this.name); // undefined
  };
}

→ クロージャは this ではなくスコープ変数を閉じ込める
→ ✅ this が必要な場合は bind やアロー関数を使う


設計戦略:クロージャを使うべき場面とは

要件 クロージャの使用 理由
内部状態を持ちたい ✅ 適している オブジェクトを使わずに状態保持できる
他から値を隠したい ✅ 有効 外部アクセスを排除できる
毎回初期化された関数が欲しい ✅ 最適 スコープ毎に独立した状態が生成される
複雑すぎる状態を管理したい ❌ 不適 ReactやVueなど、構造的に管理すべき

結語

クロージャはJavaScriptの“ふるまい”ではなく、“設計機構”である。
その本質は「状態のカプセル化」と「スコープの延命」にある。

それはただのトリックではなく、純粋関数と副作用の間にある、ミニマルで力強い表現手段だ。

意図してクロージャを使い、状態を設計し、記憶を制御できること。
それが、プロフェッショナルなJavaScript設計者の第一歩である。

2
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?