クロージャによるプライベート変数
関数スコープの内側に状態を隠します。
「クロージャによるプライベート変数」は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); // undefinedprivateな状態を持つカウンター
典型的な例は、値を直接変更できないカウンターです。値を変更できるのは、返されたメソッドだけです。
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フィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- クロージャが状態を取り込む仕組み
- クロージャによるプライベート変数
- モジュールパターン(IIFE)
- ファクトリ関数