Statische Initialisierungsblöcke
Statische Initialisierungsblöcke werden innerhalb einer Klasse
deklariert. Sie enthalten Anweisungen, die während der Klasseninitialisierung ausgewertet werden. Dies ermöglicht flexiblere Initialisierungslogik als statische
Eigenschaften, wie z.B. die Verwendung von try...catch
oder das Setzen mehrerer Felder aus einem einzigen Wert. Die Initialisierung erfolgt im Kontext der aktuellen Klassendeklaration mit Zugang zum privaten Zustand, wodurch es der Klasse ermöglicht wird, Informationen über ihre privaten Eigenschaften mit anderen Klassen oder Funktionen im gleichen Geltungsbereich zu teilen (analog zu "Freund"-Klassen in C++).
Probieren Sie es aus
class ClassWithStaticInitializationBlock {
static staticProperty1 = "Property 1";
static staticProperty2;
static {
this.staticProperty2 = "Property 2";
}
}
console.log(ClassWithStaticInitializationBlock.staticProperty1);
// Expected output: "Property 1"
console.log(ClassWithStaticInitializationBlock.staticProperty2);
// Expected output: "Property 2"
Syntax
class ClassWithSIB {
static {
// …
}
}
Beschreibung
Ohne statische Initialisierungsblöcke könnte eine komplexe statische Initialisierung durch den Aufruf einer statischen Methode nach der Klassendeklaration erreicht werden:
class MyClass {
static init() {
// Access to private static fields is allowed here
}
}
MyClass.init();
Dieser Ansatz offenbart jedoch ein Implementierungsdetail (die init()
-Methode) dem Benutzer der Klasse. Andererseits hat jede außerhalb der Klasse deklarierte Initialisierungslogik keinen Zugriff auf private statische Felder. Statische Initialisierungsblöcke erlauben die Deklaration beliebiger Initialisierungslogik innerhalb der Klasse, die während der Klassenauswertung ausgeführt wird.
Eine Klasse
kann eine beliebige Anzahl von static {}
Initialisierungsblöcken in ihrem Klassenrumpf haben. Diese werden ausgewertet, zusammen mit jeder dazwischenliegenden statischen Felde-Initialisierung, in der Reihenfolge, in der sie deklariert sind. Jede statische Initialisierung einer Superklasse wird zuerst durchgeführt, vor der Initialisierung ihrer Unterklassen.
Der Geltungsbereich der innerhalb des statischen Blocks deklarierten Variablen ist lokal für den Block. Dazu gehören var
, function
, const
und let
Deklarationen. var
-Deklarationen werden nicht aus dem statischen Block herausgehoben.
var y = "Outer y";
class A {
static field = "Inner y";
static {
// var y only hoisted inside block
console.log(y); // undefined <-- not 'Outer y'
var y = this.field;
}
}
// var y defined in static block is not hoisted
// outside the block
console.log(y); // 'Outer y'
Das this
in einem statischen Block bezieht sich auf das Konstruktorobjekt der Klasse. super.property
kann verwendet werden, um auf statische Eigenschaften der Superklasse zuzugreifen. Beachten Sie jedoch, dass es ein Syntaxfehler ist, super()
in einem statischen Initialisierungsblock einer Klasse aufzurufen oder das arguments
-Objekt zu verwenden.
Die Anweisungen werden synchron ausgewertet. Sie können await
oder yield
in diesem Block nicht verwenden. (Denken Sie an die Initialisierungsanweisungen, als ob sie implizit in eine Funktion eingebettet wären.)
Der Geltungsbereich des statischen Blocks ist innerhalb des lexikalischen Geltungsbereichs des Klassenrumpfs eingebettet und kann auf private Namen zugreifen, die innerhalb der Klasse deklariert sind, ohne einen Syntaxfehler zu verursachen.
Statische Felder Initialisierer und statische Initialisierungsblöcke werden nacheinander ausgewertet. Der Initialisierungsblock kann sich auf Werte beziehen, die über ihm stehen, aber nicht unter ihm. Alle statischen Methoden werden dabei vorab hinzugefügt und sind zugänglich, auch wenn deren Aufruf möglicherweise nicht wie erwartet funktioniert, wenn sie sich auf Felder beziehen, die unter dem aktuellen Block liegen.
Hinweis:
Dies ist besonders wichtig bei privaten statischen Feldern, da der Zugriff auf ein nicht initialisiertes privates Feld einen TypeError
auslöst, selbst wenn das private Feld darunter deklariert ist. (Wenn das private Feld nicht deklariert ist, würde es sich um einen frühen SyntaxError
handeln.)
Ein statischer Initialisierungsblock darf keine Dekorateure haben (die Klasse selbst kann jedoch welche haben).
Beispiele
Mehrere Blöcke
Der folgende Code zeigt eine Klasse mit statischen Initialisierungsblöcken und dazwischenliegenden statischen Felde-Initialisierern. Die Ausgabe zeigt, dass die Blöcke und Felder in Ausführungsreihenfolge ausgewertet werden.
class MyClass {
static field1 = console.log("static field1");
static {
console.log("static block1");
}
static field2 = console.log("static field2");
static {
console.log("static block2");
}
}
// 'static field1'
// 'static block1'
// 'static field2'
// 'static block2'
Beachten Sie, dass jede statische Initialisierung einer Superklasse zuerst durchgeführt wird, bevor die ihrer Unterklassen erfolgt.
Verwendung von this und super
Das this
in einem statischen Block bezieht sich auf das Konstruktorobjekt der Klasse. Dieser Code zeigt, wie auf ein öffentliches statisches Feld zugegriffen wird.
class A {
static field = "static field";
static {
console.log(this.field);
}
}
// 'static field'
Die super.property
Syntax kann innerhalb eines static
Blocks verwendet werden, um statische Eigenschaften einer Superklasse zu referenzieren.
class A {
static field = "static field";
}
class B extends A {
static {
console.log(super.field);
}
}
// 'static field'
Zugriff auf private Eigenschaften
Das folgende Beispiel zeigt, wie der Zugriff auf ein privates Instanzfeld einer Klasse von einem Objekt außerhalb der Klasse gewährt werden kann (Beispiel vom v8.dev Blog):
let getDPrivateField;
class D {
#privateField;
constructor(v) {
this.#privateField = v;
}
static {
getDPrivateField = (d) => d.#privateField;
}
}
console.log(getDPrivateField(new D("private"))); // 'private'
Spezifikationen
Specification |
---|
ECMAScript® 2025 Language Specification # prod-ClassStaticBlock |
Browser-Kompatibilität
Siehe auch
- Verwendung von Klassen Leitfaden
- Klassen
static
class
- Klassen-statische Initialisierungsblöcke auf v8.dev (2021)
- ES2022 Feature: Klassen-statische Initialisierungsblöcke von Dr. Axel Rauschmayer (2021)