Statische Initialisierungsblöcke
Statische Initialisierungsblöcke werden innerhalb einer Klasse
deklariert. Sie enthalten Anweisungen, die während der Initialisierung der Klasse ausgewertet werden. Dies ermöglicht eine flexiblere Initialisierungslogik als statische
Eigenschaften, wie beispielsweise die Verwendung von try...catch
oder das Setzen mehrerer Felder aus einem einzigen Wert. Die Initialisierung erfolgt im Kontext der aktuellen Klassendeklaration mit Zugang zu privatem Status, was es der Klasse ermöglicht, Informationen ihrer privaten Elemente mit anderen Klassen oder Funktionen im selben Gültigkeitsbereich 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 es, beliebige Initialisierungslogik innerhalb der Klasse zu deklarieren und während der Klassenauswertung auszuführen.
Eine Klasse
kann eine beliebige Anzahl von static {}
Initialisierungsblöcken in ihrem Klassenkörper haben.
Diese werden ausgewertet, zusammen mit interleaved statischen Feldinitialisierern, in der Reihenfolge, in der sie deklariert sind.
Jede statische Initialisierung einer Oberklasse wird zuerst durchgeführt, vor der ihrer Unterklassen.
Die Reichweite der innerhalb des statischen Blocks deklarierten Variablen ist lokal zum Block. Dies schließt var
, function
, const
und let
Deklarationen ein. 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'
this
innerhalb eines statischen Blocks bezieht sich auf das Konstruktorobjekt der Klasse.
super.property
kann verwendet werden, um auf statische Eigenschaften der Oberklasse zuzugreifen.
Beachten Sie jedoch, dass es ein Syntaxfehler ist, super()
in einem statischen Initialisierungsblock der Klasse aufzurufen oder das arguments
Objekt zu verwenden.
Die Anweisungen werden synchron ausgewertet. Es ist nicht möglich, await
oder yield
in diesem Block zu verwenden. (Betrachten Sie die Initialisierungsanweisungen als implizit in eine Funktion gewickelt.)
Der Gültigkeitsbereich des statischen Blocks ist innerhalb des lexikalischen Gültigkeitsbereichs des Klassenkörpers verschachtelt und hat Zugriff auf private Namen, die innerhalb der Klasse deklariert sind, ohne einen Syntaxfehler zu verursachen.
Statische Felder Initialisierer und statische Initialisierungsblöcke werden einzeln ausgewertet. Der Initialisierungsblock kann sich auf Feldwerte oberhalb davon beziehen, aber nicht darunter. Alle statischen Methoden werden vorher hinzugefügt und können zugegriffen werden, obwohl deren Aufruf möglicherweise nicht wie erwartet funktioniert, wenn sie sich auf Felder unterhalb des aktuellen Blocks beziehen.
Hinweis:
Dies ist wichtiger 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äre es ein früher SyntaxError
.)
Ein statischer Initialisierungsblock darf keine Dekoratoren haben (die Klasse selbst kann jedoch).
Beispiele
Mehrere Blöcke
Der folgende Code zeigt eine Klasse mit statischen Initialisierungsblöcken und dazwischen liegenden statischen Feldinitialisierern. Die Ausgabe zeigt, dass die Blöcke und Felder in der 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 Oberklasse zuerst durchgeführt wird, vor der ihrer Unterklassen.
Verwendung von this und super
Das this
innerhalb eines statischen Blocks bezieht sich auf das Konstruktorobjekt der Klasse. Dieser Code zeigt, wie auf ein öffentliches statisches Feld zugegriffen werden kann.
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 Oberklasse zu referenzieren.
class A {
static field = "static field";
}
class B extends A {
static {
console.log(super.field);
}
}
// 'static field'
Zugriff auf private Elemente
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 aus dem 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
No specification found
No specification data found for javascript.classes.static_initialization_blocks
.
Check for problems with this page or contribute a missing spec_url
to mdn/browser-compat-data. Also make sure the specification is included in w3c/browser-specs.
Browser-Kompatibilität
Siehe auch
- Verwendung von Klassen Leitfaden
- Klassen
static
class
- Klassenstatische Initialisierungsblöcke auf v8.dev (2021)
- ES2022 Funktion: Klassenstatische Initialisierungsblöcke von Dr. Axel Rauschmayer (2021)