Start · Sprachen · JavaScript · Referenz · class expression

class expression

Operator

Das <code>class</code>-Schlüsselwort definiert eine Klasse innerhalb eines Ausdrucks — anonym oder benannt — und gibt sie als Wert zurück.

seit JavaScript ES2015 Kategorie: syntax

Signatur

const MyClass = class [ClassName] { /* Klassenkörper */ }

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

Typ
Function
Beschreibung
Gibt das Klassenobjekt zurück (intern ein 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
Mieze macht ein Geräusch. Animal

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.');
}
55 undefined

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.');
[APP] Server gestartet. [DB] 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
3

// 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 { … } ist Bar nur innerhalb des Klassenkörpers gültig. Foo.name gibt "Bar" zurück, aber Bar außerhalb des Ausdrucks ist undefined.
  • 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+).