静态初始化块

静态初始化块是在 class 内声明的。它包含在类初始化期间要执行的语句。这允许比 static 属性更灵活的初始化逻辑,例如使用 try...catch 或从单个值设置多个字段。初始化在当前类声明的上下文中执行,可以访问私有状态,这使得类可以与在相同范围内声明的其他类或函数共享其私有属性的信息(类似于 C++ 中的 "friend" 类)。

试试看

语法

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 = this.field;
  }
}

// var defined in static block is not hoisted
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'

super.property 语法可以在 static 块中使用,以引用超类的静态属性。

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 语言规范
# prod-ClassStaticBlock

浏览器兼容性

BCD 表格仅在浏览器中加载

参见