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

js
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:

js
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.

js
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.

js
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.

js
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.

js
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):

js
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