2
2

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

概要

クロージャ(Closure)は、JavaScriptの関数がスコープ外の変数を保持し続ける能力を指す。
それは「関数の外で定義された変数が、関数の内側で使える」という表面的な便利さを超え、**状態と関数の統合(=関数による状態のカプセル化)**を実現する。

本記事では、クロージャの本質・使い所・メリット・設計上の注意点を構造的に整理し、ただ使うだけでなく、使いこなすための戦略を提示する。


クロージャとは何か?

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

const counter = createCounter();
counter(); // 1
counter(); // 2
  • countcreateCounter() のスコープ内で定義された変数
  • ✅ 内部関数が count を“捕捉(close over)”して保持している

→ これがクロージャ


クロージャが使われる代表的パターン

✅ 状態のカプセル化(データの隠蔽)

function userFactory(name) {
  let secret = 'classified';

  return {
    getName: () => name,
    getSecret: () => secret,
    setSecret: (s) => { secret = s; }
  };
}

const u = userFactory('toto');
u.getSecret();       // 'classified'
u.setSecret('X');    // 更新可

→ ✅ secret は外部から直接アクセスできず、関数経由でのみ操作可能


✅ 関数ファクトリ(設定を固定した関数を生成)

function multiplier(factor) {
  return (n) => n * factor;
}

const double = multiplier(2);
double(5); // 10

→ ✅ パラメータを持った「関数の雛形」が生成できる


✅ コールバック内での状態保持

function setupLogger() {
  let logs = [];
  return function (msg) {
    logs.push(msg);
    console.log(logs.join(' / '));
  };
}

const logger = setupLogger();
logger('A'); // A
logger('B'); // A / B

クロージャを使うメリット

効果 説明
データの隠蔽 直接アクセスできない変数として保持
状態の永続化 関数が実行された後も値が保持され続ける
高度な再利用性 パラメータを記憶した関数を生成できる
コールバックの文脈維持 setTimeout, Promise 内などで状態を維持可能

設計上の注意点

❌ 意図しないメモリ保持(メモリリーク)

function leak() {
  let huge = new Array(1_000_000).fill('x');
  return () => huge;
}
  • huge はGCされない → 無駄にメモリを消費
  • ❌ 呼び出されない関数でも変数を保持し続ける

→ 🔧 対策:スコープの寿命を最小限に設計


❌ クロージャで値が“固定”されていない場合の誤解

let funcs = [];
for (var i = 0; i < 3; i++) {
  funcs.push(() => i);
}

funcs[0](); // 3 ❌
funcs[1](); // 3 ❌

→ 🔧 対策:let or IIFEでスコープを分離

for (let i = 0; i < 3; i++) {
  funcs.push(() => i); // ✅ 0, 1, 2
}

クロージャの使用判断フロー

① 状態を外部から隠したい? → クロージャでカプセル化

② 関数に設定を埋め込みたい? → クロージャで関数ファクトリ

③ コールバック内で値を保持したい? → クロージャで値を囲い込む

④ 状態が巨大 / 不定多数? → クロージャは避け、構造体や外部記憶を使う

結語

クロージャは、単なる便利な“テクニック”ではない。
それは「関数に状態を持たせ、設計に責任を与える構文」である。

  • 関数が“値を記憶する”ことで、一貫性と隠蔽性を同時に実現
  • 外部から見えないスコープが、ロジックの防御壁となる
  • ただし、“覚えてしまう”がゆえに、適切な開放・スコープ設計が不可欠

クロージャとは、“設計された記憶”である。

2
2
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
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?