0Pricing
JavaScript Academy · レッスン

クロージャによるプライベート変数

関数スコープの内側に状態を隠します。

「クロージャによるプライベート変数」はCoddyKit上の無料JavaScript Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJavaScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 JavaScript Academyコースには全4レッスンが含まれています。

クロージャによるプライバシー

JavaScriptには長い間、オブジェクトのフィールドをprivateにする組み込みの方法がありませんでした。クロージャを使えばその方法を実現できます。関数内の変数は外部から見えませんが、その関数内で定義された関数からはアクセスできます。

function secretBox() {
  let secret = "hidden";
  return {
    reveal: () => secret
  };
}
const box = secretBox();
console.log(box.reveal()); // "hidden"
console.log(box.secret);   // undefined

privateな状態を持つカウンター

典型的な例は、値を直接変更できないカウンターです。値を変更できるのは、返されたメソッドだけです。

function makeCounter() {
  let count = 0;
  return {
    increment: () => ++count,
    value: () => count
  };
}
const c = makeCounter();
c.increment();
c.increment();
console.log(c.value()); // 2

状態には触れられない

外部からcountに到達する方法はありません。読み取ろうとしてもundefinedが返されるため、必ずメソッドを介する必要があります。

function makeCounter() {
  let count = 0;
  return { inc: () => ++count, get: () => count };
}
const c = makeCounter();
c.count = 100;        // creates an unrelated property
console.log(c.get()); // 0 - real count untouched

ルールを適用する

メソッドを介してアクセスするため、残高を決してマイナスにしないなどの不変条件を適用できます。

function account(start) {
  let balance = start;
  return {
    withdraw: (n) => {
      if (n > balance) return "insufficient";
      balance -= n;
      return balance;
    },
    balance: () => balance
  };
}
const a = account(100);
console.log(a.withdraw(150)); // "insufficient"
console.log(a.withdraw(40));  // 60

複数のprivateフィールド

1つのクロージャで複数の変数を同時に保護できます。それらはすべて隠され、返されたメソッド間でのみ共有されます。

function user(name) {
  let logins = 0;
  let lastSeen = null;
  return {
    login: () => { logins++; lastSeen = "now"; },
    stats: () => ({ name, logins, lastSeen })
  };
}
const u = user("Ada");
u.login();
console.log(u.stats()); // { name: "Ada", logins: 1, lastSeen: "now" }

privateなヘルパー関数

隠せるのはデータだけではありません。内部関数も隠せます。公開するメソッドだけがpublicになります。

function temperature() {
  let celsius = 0;
  const toF = (c) => c * 9 / 5 + 32; // private
  return {
    set: (c) => { celsius = c; },
    fahrenheit: () => toF(celsius)
  };
}
const t = temperature();
t.set(100);
console.log(t.fahrenheit()); // 212

独立したインスタンス

ファクトリーを呼び出すたびに別々のprivateな状態が作られるため、インスタンス同士が干渉することはありません。

function makeCounter() {
  let n = 0;
  return { inc: () => ++n };
}
const a = makeCounter();
const b = makeCounter();
console.log(a.inc(), a.inc()); // 1 2
console.log(b.inc());          // 1

読み取り専用で公開する

setterを用意せずにgetterだけを公開すると、内部では変更可能な値を外部からは読み取り専用にできます。

function timer() {
  let ticks = 0;
  setupInternally();
  function setupInternally() { ticks = 3; }
  return { ticks: () => ticks };
}
const t = timer();
console.log(t.ticks()); // 3 - no way to set it outside

比較:クラスフィールド

現在のJavaScriptでは、#privateクラスフィールドもサポートされています。クロージャは、ファクトリー関数やクラスを使わずにプライバシーを実現したい場合に、引き続き役立ちます。

class Counter {
  #count = 0;
  inc() { return ++this.#count; }
}
const c = new Counter();
console.log(c.inc()); // 1

機能する仕組み

返されるメソッドは、外側の変数を取り込んだクロージャです。外側の関数はすでに戻っていますが、それらのクロージャが外側の関数を参照し続けるため、そのスコープは存続します。

メモ化キャッシュ

privateな状態はキャッシュに最適です。キャッシュオブジェクトは隠されたまま、呼び出しの間も保持されます。

function memoSquare() {
  const cache = {};
  return (n) => {
    if (cache[n] === undefined) cache[n] = n * n;
    return cache[n];
  };
}
const sq = memoSquare();
console.log(sq(4)); // 16
console.log(sq(4)); // 16 (cached)

クイックチェック

クロージャによるprivateな変数

まとめ

クロージャはプライバシーを実現します。ファクトリー内の変数は外部から到達できませんが、返されたメソッド間では共有されます。これにより、改ざんできないカウンター、不変条件を守る残高、隠されたヘルパー、キャッシュを実現できます。ファクトリーを呼び出すたびに独立した状態が作られます。最新の#privateクラスフィールドは代替手段ですが、ファクトリー形式のコードではクロージャが特に力を発揮します。

よくある質問

「クロージャによるプライベート変数」レッスンは無料ですか?

はい。「クロージャによるプライベート変数」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、JavaScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 JavaScript Academyコースには全4レッスンが含まれています。

「クロージャによるプライベート変数」で何を学びますか?

関数スコープの内側に状態を隠します。 ブラウザで直接実行するハンズオンコードでJavaScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

JavaScript Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのJavaScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「クロージャによるプライベート変数」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このJavaScript Academyレッスンでコードを書いて実行できますか?

はい。すべてのJavaScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. クロージャが状態を取り込む仕組み
  2. クロージャによるプライベート変数
  3. モジュールパターン(IIFE)
  4. ファクトリ関数
← JavaScript Academyに戻る