Signatur
Beschreibung
Mit öffentlichen Klassenfeldern deklarieren Sie Eigenschaften direkt im Klassenrumpf, statt sie im constructor per this.x = … zuzuweisen. Jedes Instanzfeld wird für jede neue Instanz als eigene Eigenschaft angelegt, also nicht auf dem Prototyp. Die Semantik entspricht Object.defineProperty() mit writable, enumerable und configurable jeweils auf true.
Statische Felder (static name = wert) werden einmalig auf dem Klassenkonstruktor selbst definiert, zum Beispiel für Konstanten, Zähler oder Caches. Der Initialisierer wird beim Auswerten der Klassendefinition ausgeführt, und this verweist dort auf die Klasse.
Initialisierer von Instanzfeldern werden bei jeder Instanziierung ausgewertet, und zwar in der Reihenfolge ihrer Deklaration. In Basisklassen passiert das direkt zu Beginn des Konstruktors, in abgeleiteten Klassen unmittelbar nachdem super() zurückgekehrt ist. Innerhalb des Initialisierers verweist this auf die entstehende Instanz. Deshalb eignen sich Felder mit Pfeilfunktionen gut für Event-Handler, deren this fest an die Instanz gebunden sein soll.
Feldnamen können Bezeichner, Zeichenketten, Zahlen oder berechnete Schlüssel ([ausdruck]) sein. Ein Feld ohne Initialisierer erhält den Wert undefined. Für wirklich gekapselte Daten gibt es private Felder mit dem Präfix #.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $static | Schlüsselwort | Optional. Definiert das Feld auf dem Klassenkonstruktor statt auf jeder Instanz. | |
| $feldName Pflicht | Bezeichner | string | number | [berechneter Schlüssel] | Name der Eigenschaft. Berechnete Schlüssel wie [Symbol.iterator] werden nur einmal ausgewertet, und zwar beim Auswerten der Klassendefinition. |
|
| $initialwert | any | undefined | Ausdruck, der bei jeder Instanziierung (bzw. einmalig bei static) ausgewertet wird. this verweist auf die Instanz bzw. auf die Klasse. |
Rückgabewert
Beispiele
Instanzfelder statt Konstruktor-Zuweisungen
class Warenkorb {
artikel = [];
rabatt = 0;
waehrung = 'EUR';
hinzufuegen(name, preis) {
this.artikel.push({ name, preis });
return this;
}
get summe() {
const brutto = this.artikel.reduce((s, a) => s + a.preis, 0);
return brutto * (1 - this.rabatt);
}
}
const korb = new Warenkorb().hinzufuegen('Buch', 20).hinzufuegen('Stift', 5);
korb.rabatt = 0.1;
console.log(korb.summe, korb.waehrung);
console.log(Object.keys(korb));
Statische Felder für Konstanten und Zähler
class Benutzer {
static anzahl = 0;
static ROLLEN = Object.freeze(['gast', 'nutzer', 'admin']);
id = ++Benutzer.anzahl;
rolle = Benutzer.ROLLEN[0];
constructor(name) {
this.name = name;
}
}
const a = new Benutzer('Anna');
const b = new Benutzer('Ben');
console.log(a.id, b.id, Benutzer.anzahl);
console.log(b.rolle, 'anzahl' in b);
Pfeilfunktion als gebundener Event-Handler
class Zaehler {
wert = 0;
// this ist dauerhaft an die Instanz gebunden
erhoehen = () => {
this.wert++;
console.log(`Wert: ${this.wert}`);
};
}
const z = new Zaehler();
const handler = z.erhoehen; // Methode vom Objekt gelöst
handler();
setTimeout(z.erhoehen, 0);
// Im Browser: button.addEventListener('click', z.erhoehen);
Initialisierungsreihenfolge bei Vererbung
class Basis {
typ = 'basis';
constructor() {
console.log('Basis-Konstruktor sieht:', this.typ);
}
}
class Kind extends Basis {
typ = 'kind';
constructor() {
super(); // Kind-Felder existieren erst nach super()
console.log('Kind-Konstruktor sieht:', this.typ);
}
}
new Kind();
// Wichtig · Fallstricke
- Definieren statt Zuweisen: Felder werden per
[[DefineOwnProperty]]angelegt, nicht per Zuweisung. Setter der Oberklasse werden daher nicht aufgerufen. Stattdessen überdeckt das Feld den Accessor mit einer eigenen Dateneigenschaft. Das weicht vonthis.x = …im Konstruktor ab und auch von älteren Babel- oder TypeScript-Einstellungen (useDefineForClassFields: false). - Reihenfolge bei Vererbung: Die Felder einer Unterklasse gibt es erst nach
super(). Ruft der Konstruktor der Basisklasse eine überschriebene Methode auf, die auf solche Felder zugreift, liest dieseundefined. - Speicherbedarf: Pfeilfunktionen in Feldern werden für jede Instanz neu erzeugt und liegen nicht auf dem Prototyp. Bei sehr vielen Instanzen kostet das mehr Speicher, außerdem lassen sie sich nicht per
super.methode()aufrufen. - Veränderliche Standardwerte wie
artikel = []sind unbedenklich. Der Initialisierer läuft für jede Instanz neu, die Instanzen teilen sich also kein Array. - Felder, deren Name
constructorlautet, sind nicht erlaubt. Auch statische Felder mit den Namenprototypeoderconstructorsind verboten. - In Initialisierern ist
argumentsnicht verfügbar (SyntaxError). - Kompatibilität: Unterstützt in Chrome 72+, Firefox 69+ (statische Felder ab 75), Safari 14+ (statische Felder ab 14.1) und Node.js 12+. Für ältere Umgebungen ist eine Transpilierung nötig.