Closure
Kurz: Eine Closure (Funktionsabschluss) ist eine Funktion, die sich die Variablen ihrer Umgebung „merkt“ – auch dann noch, wenn die äußere Funktion längst beendet ist.
Genauer: Closures entstehen, wenn eine innere Funktion auf Variablen der äußeren zugreift und zurückgegeben oder weitergereicht wird. Sie sind die Grundlage für Zähler, Fabriken, Callbacks, Teilanwendung (Currying) und das Modul-Muster in JavaScript. Unterstützt werden sie von JavaScript, Python, Java (Lambda-Ausdrücke), C#, Go, Kotlin, Swift, Rust, Haskell und vielen weiteren.
Im Detail
def zaehler():
stand = 0
def erhoehe():
nonlocal stand
stand += 1
return stand
return erhoehe
a = zaehler()
b = zaehler()
print(a(), a(), a()) # 1 2 3
print(b()) # 1 (eigener, getrennter Zustand)function multiplikator(faktor) {
return (x) => x * faktor; // merkt sich "faktor"
}
const verdopple = multiplikator(2);
const verdreifache = multiplikator(3);
console.log(verdopple(10), verdreifache(10)); // 20 30Wofür?
- Zustand kapseln: Die Variable
standist von außen nicht erreichbar, nur über die zurückgegebene Funktion – ähnlich wie ein privates Feld in der Kapselung. - Funktionen konfigurieren:
multiplikator(2)erzeugt eine spezialisierte Funktion. - Ereignisbehandlung: Ein Event-Handler greift auf Daten aus dem Kontext zu, in dem er erstellt wurde.
Stolperfalle: Schleifenvariable
In JavaScript fangen Closures über var dieselbe Variable ein: Alle Handler sehen am Ende denselben Wert. let erzeugt pro Durchlauf eine neue Variable und löst das Problem.
const mitVar = [], mitLet = [];
for (var i = 0; i < 3; i++) mitVar.push(() => i);
for (let j = 0; j < 3; j++) mitLet.push(() => j);
console.log(mitVar.map((f) => f())); // [3, 3, 3]
console.log(mitLet.map((f) => f())); // [0, 1, 2]Siehe auch: Lambda-Ausdruck, Higher-Order-Funktion, Callback, Kapselung