靜態初始化塊

Baseline 已廣泛支援

此功能已成熟,並可在許多裝置和瀏覽器版本上執行。自 2023 年 3 月以來,它已在各種瀏覽器中可用。

靜態初始化塊宣告在 class 內部。它包含在類初始化期間需要評估的語句。這允許比 static 屬性更靈活的初始化邏輯,例如使用 try...catch 或從單個值設定多個欄位。初始化在當前類宣告的上下文中執行,可以訪問私有狀態,這允許類與其在同一作用域中宣告的其他類或函式共享其私有元素的資訊(類似於 C++ 中的“友元”類)。

試一試

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"

語法

js
class ClassWithSIB {
  static {
    // …
  }
}

描述

如果沒有靜態初始化塊,複雜的靜態初始化可以透過在類聲明後呼叫靜態方法來實現

js
class MyClass {
  static init() {
    // Access to private static fields is allowed here
  }
}

MyClass.init();

然而,這種方法將實現細節(init() 方法)暴露給類的使用者。另一方面,在類外部宣告的任何初始化邏輯都無法訪問私有靜態欄位。靜態初始化塊允許在類內部宣告任意初始化邏輯,並在類評估期間執行。

一個 class 可以在其類主體中擁有任意數量的 static {} 初始化塊。它們與任何穿插的靜態欄位初始化器一起,按照宣告的順序進行評估。任何超類的靜態初始化都會首先執行,然後才是其子類的靜態初始化。

靜態塊內宣告的變數作用域僅限於該塊。這包括 varfunctionconstlet 宣告。var 宣告不會被提升到靜態塊之外。

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'

靜態塊內的 this 指的是類的建構函式物件。super.property 可用於訪問超類的靜態屬性。但是請注意,在類靜態初始化塊中呼叫 super(),或使用 arguments 物件是語法錯誤。

語句是同步評估的。你不能在此塊中使用 awaityield。(可以將初始化語句看作是被隱式包裹在一個函式中。)

靜態塊的作用域巢狀在類主體的詞法作用域之內,並且可以訪問在類內部宣告的私有名稱,而不會導致語法錯誤。

靜態欄位初始化器和靜態初始化塊是逐個評估的。初始化塊可以引用其上方的欄位值,但不能引用其下方的欄位值。所有靜態方法都會預先新增並可以訪問,儘管如果它們引用當前塊下方的欄位,則呼叫它們可能不會按預期執行。

注意: 這對於私有靜態欄位更為重要,因為即使私有欄位在下方宣告,訪問未初始化的私有欄位也會丟擲 TypeError。(如果私有欄位未宣告,則會是一個早期 SyntaxError。)

靜態初始化塊不能有裝飾器(類本身可以有)。

示例

多個塊

下面的程式碼演示了一個包含靜態初始化塊和穿插的靜態欄位初始化器的類。輸出顯示塊和欄位是按執行順序評估的。

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'

請注意,任何超類的靜態初始化都會首先執行,然後才是其子類的靜態初始化。

使用 this 和 super

靜態塊內的 this 指的是類的建構函式物件。此程式碼顯示瞭如何訪問公共靜態欄位。

js
class A {
  static field = "static field";
  static {
    console.log(this.field);
  }
}
// 'static field'

可以在 static 塊內使用 super.property 語法來引用超類的靜態屬性。

js
class A {
  static field = "static field";
}

class B extends A {
  static {
    console.log(super.field);
  }
}
// 'static field'

訪問私有元素

下面的示例展示瞭如何從類外部的物件授予對類私有例項欄位的訪問許可權(示例來自 v8.dev 部落格

js
let getDPrivateField;

class D {
  #privateField;
  constructor(v) {
    this.#privateField = v;
  }
  static {
    getDPrivateField = (d) => d.#privateField;
  }
}

console.log(getDPrivateField(new D("private"))); // 'private'

規範

規範
ECMAScript® 2026 語言規範
# prod-ClassStaticBlock

瀏覽器相容性

另見