Signatur
Beschreibung
Ein Klassenausdruck (englisch: class expression) ist eine der zwei Möglichkeiten, in JavaScript eine Klasse zu definieren. Im Gegensatz zur Klassendeklaration (class Foo { … }) ist ein Klassenausdruck ein Ausdruck, der einen Klassenwert erzeugt und direkt einer Variablen, einem Parameter oder einem anderen Ausdruck zugewiesen werden kann.
Klassenausdrücke können anonym (ohne Namen) oder benannt (mit optionalem Klassennamen nach dem class-Schlüsselwort) sein. Ein benannter Klassenausdruck macht den internen Namen nur innerhalb des Klassenkörpers sichtbar — außerhalb der Klasse ist er nicht zugänglich. Das ist nützlich für rekursive Methoden oder selbstreferenzierende Klassen.
Wie Klassendeklarationen unterstützen Klassenausdrücke alle modernen OOP-Merkmale: constructor, Instanz- und statische Methoden, Getter/Setter, öffentliche und private Felder (#field), extends für Vererbung sowie super. Im Gegensatz zu Funktionsausdrücken werden Klassenausdrücke nicht gehoben (kein Hoisting) und befinden sich bis zur Auswertung in der Temporal Dead Zone.
Klassenausdrücke eignen sich besonders dann, wenn Klassen dynamisch erzeugt, als Rückgabewert von Factory-Funktionen geliefert oder als Argument an Higher-Order-Funktionen übergeben werden sollen — überall dort, wo eine Klasse als First-Class-Wert behandelt wird.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $ClassName | string | Optionaler interner Name der Klasse. Nur innerhalb des Klassenkörpers sichtbar. Außerhalb ist der Name nicht zugreifbar; der Bezeichner der Variablen, der der Ausdruck zugewiesen wird, dient als externer Name. |
Rückgabewert
Function-Objekt), das anschließend mit new instanziiert oder weitergegeben werden kann.Beispiele
Anonymer Klassenausdruck
const Animal = class {
constructor(name) {
this.name = name;
}
speak() {
return `${this.name} macht ein Geräusch.`;
}
};
const cat = new Animal('Mieze');
console.log(cat.speak());
console.log(Animal.name); // interner Name ist leer → Variablenname wird verwendet
Benannter Klassenausdruck — interner Name nur im Klassenkörper
const Fibonacci = class FibClass {
constructor(n) {
this.n = n;
}
compute() {
if (this.n <= 1) return this.n;
// Rekursion über internen Klassennamen FibClass
return new FibClass(this.n - 1).compute() + new FibClass(this.n - 2).compute();
}
};
console.log(new Fibonacci(10).compute()); // 55
try {
// FibClass ist außerhalb NICHT sichtbar
console.log(typeof FibClass);
} catch (e) {
console.log('FibClass ist außen nicht definiert.');
}
Klasse als Rückgabewert einer Factory-Funktion
const createLogger = (prefix) => class {
log(msg) {
console.log(`[${prefix}] ${msg}`);
}
};
const AppLogger = createLogger('APP');
const DbLogger = createLogger('DB');
new AppLogger().log('Server gestartet.');
new DbLogger().log('Verbindung hergestellt.');
Klassenausdruck mit Vererbung und privaten Feldern
const Counter = class {
#count = 0;
increment() { this.#count++; }
decrement() { this.#count--; }
get value() { return this.#count; }
};
const BoundedCounter = class extends Counter {
#max;
constructor(max) {
super();
this.#max = max;
}
increment() {
if (this.value < this.#max) super.increment();
}
};
const c = new BoundedCounter(3);
c.increment(); c.increment(); c.increment(); c.increment();
console.log(c.value); // 3 — Grenze eingehalten
// Wichtig · Fallstricke
Kein Hoisting: Klassenausdrücke werden — wie Klassendeklarationen — nicht in den Scope-Anfang gehoben. Der Zugriff vor der Auswertung führt zu einem ReferenceError (Temporal Dead Zone).
- Strikter Modus: Der gesamte Klassenkörper wird automatisch im strict mode ausgeführt, unabhängig von der äußeren Umgebung.
- Interner vs. externer Name: Bei
const Foo = class Bar { … }istBarnur innerhalb des Klassenkörpers gültig.Foo.namegibt"Bar"zurück, aberBaraußerhalb des Ausdrucks istundefined. - Klassenausdruck vs. Klassendeklaration: Funktional gleichwertig; Klassenausdrücke erlauben aber dynamische Erzeugung und den Einsatz als First-Class-Wert (z. B. als Argument oder Rückgabewert).
- Browser-Kompatibilität: Vollständig unterstützt in allen modernen Browsern und Node.js ab Version 6. Private Felder (
#field) erfordern modernere Laufzeiten (Chrome 74+, Node.js 12+).