Beherrsche, wie Closures Variablen einfangen, damit du Zustand kapseln und Fallstricke beim Gültigkeitsbereich vermeiden kannst.
Diese Lektion in Kodokon öffnenEine Closure ist kein exotischer Trick: Sie ist der Mechanismus, durch den eine Funktion Zugriff auf den lexikalischen Gültigkeitsbereich behält, in dem sie definiert wurde, nicht auf den, in dem sie aufgerufen wird. Die Engine kopiert keine Werte: Sie behält eine lebendige Referenz auf die lexikalische Umgebung. Zwei Aufrufe derselben Factory erzeugen daher zwei unabhängige Umgebungen, was Closures zum leichtgewichtigsten Kapselungswerkzeug der Sprache macht.
function createCounter() {
let count = 0;
return {
increment: () => ++count,
reset: () => { count = 0; },
};
}
const counterA = createCounter();
const counterB = createCounter();
counterA.increment();
counterA.increment();
console.log(counterA.increment()); // 3
console.log(counterB.increment()); // 1Die klassische Falle aus der Praxis: var ist an die umgebende Funktion gebunden, nicht an den Block. Innerhalb einer Schleife fängt dann jede Closure dieselbe Variable ein. Mit let erzeugt jede Iteration eine frische lexikalische Umgebung, sodass jede Erfassung eigenständig ist. Hinzu kommt die temporale tote Zone (TDZ): Eine let- oder const-Variable existiert, sobald der Block betreten wird, wirft aber einen ReferenceError, wenn du sie vor ihrer Deklaration liest.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0); // 3, 3, 3
}
for (let j = 0; j < 3; j++) {
setTimeout(() => console.log(j), 0); // 0, 1, 2
}Was Muster angeht, sind Closures die Grundlage von Memoization und dem Modul-Muster. Im Vergleich zu einer Klasse gibt dir eine Closure echte Privatsphäre ohne this oder Prototypen, um den Preis eines etwas höheren Speicherverbrauchs, wenn du Tausende Instanzen erzeugst: Jede Instanz trägt ihre eigenen Funktionen.
function memoize(fn) {
const cache = new Map();
return function (key) {
if (cache.has(key)) return cache.get(key);
const result = fn(key);
cache.set(key, result);
return result;
};
}
const square = (n) => n * n;
const fastSquare = memoize(square);
console.log(fastSquare(9)); // computed
console.log(fastSquare(9)); // read from the cachefor (var i = ...)-Schleife drei setTimeout-Callbacks aus, die im Schleifenkörper erzeugt werden?createCounter, dass count privat bleibt?