静态初始化块

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

¥Static initialization blocks are declared within a class. It contains statements to be evaluated during class initialization. This permits more flexible initialization logic than static properties, such as using try...catch or setting multiple fields from a single value. Initialization is performed in the context of the current class declaration, with access to private state, which allows the class to share information of its private properties with other classes or functions declared in the same scope (analogous to "friend" classes in C++).

Try it

语法

¥Syntax

js
class ClassWithSIB {
  static {
    // …
  }
}

描述

¥Description

如果没有静态初始化块,可以通过在类声明后调用静态方法来实现复杂的静态初始化:

¥Without static initialization blocks, complex static initialization might be achieved by calling a static method after the class declaration:

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

MyClass.init();

然而,这种方法向类的用户公开了实现细节(init() 方法)。另一方面,在类外部声明的任何初始化逻辑都无法访问私有静态字段。静态初始化块允许在类内声明任意初始化逻辑并在类求值期间执行。

¥However, this approach exposes an implementation detail (the init() method) to the user of the class. On the other hand, any initialization logic declared outside the class does not have access to private static fields. Static initialization blocks allow arbitrary initialization logic to be declared within the class and executed during class evaluation.

class 在其类主体中可以有任意数量的 static {} 初始化块。这些是 evaluated 以及任何交错的静态字段初始值设定项,按照声明的顺序排列。超类的任何静态初始化都会先执行,然后才是其子类的静态初始化。

¥A class can have any number of static {} initialization blocks in its class body. These are evaluated, along with any interleaved static field initializers, in the order they are declared. Any static initialization of a super class is performed first, before that of its sub classes.

静态块内声明的变量的范围是该块的局部范围。这包括 varfunctionconstlet 声明。块中的 var 声明不会被提升。

¥The scope of the variables declared inside the static block is local to the block. This includes var, function, const, and let declarations. var declarations in the block are not hoisted.

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 对象是语法错误。

¥The this inside a static block refers to the constructor object of the class. super.property can be used to access static properties of the super class. Note however that it is a syntax error to call super() in a class static initialization block, or to use the arguments object.

这些语句是同步评估的。你不能在此块中使用 awaityield。(将初始化语句视为隐式封装在函数中。)

¥The statements are evaluated synchronously. You cannot use await or yield in this block. (Think of the initialization statements as being implicitly wrapped in a function.)

static 块的作用域嵌套在类主体的词法作用域内,并且可以访问类内声明的 私有名称 而不会导致语法错误。

¥The scope of the static block is nested within the lexical scope of the class body, and can access private names declared within the class without causing a syntax error.

静态场 初始化程序和静态初始化块是一一评估的。初始化块可以引用其上方的字段值,但不能引用其下方的字段值。所有静态方法都是预先添加的并且可以访问,但如果它们引用当前块下方的字段,则调用它们可能不会按预期运行。

¥Static field initializers and static initialization blocks are evaluated one-by-one. The initialization block can refer to field values above it, but not below it. All static methods are added beforehand and can be accessed, although calling them may not behave as expected if they refer to fields below the current block.

注意:这对于 私有静态字段 来说更为重要,因为访问未初始化的私有字段会抛出 TypeError,即使私有字段在下面声明。(如果不声明私有字段,那就是早期的 SyntaxError。)

¥Note: This is more important with private static fields, because accessing a non-initialized private field throws a TypeError, even if the private field is declared below. (If the private field is not declared, it would be an early SyntaxError.)

静态初始化块可能没有装饰器(类本身可以)。

¥A static initialization block may not have decorators (the class itself may).

示例

¥Examples

多个区块

¥Multiple blocks

下面的代码演示了一个具有静态初始化块和交错静态字段初始值设定项的类。输出显示块和字段是按执行顺序求值的。

¥The code below demonstrates a class with static initialization blocks and interleaved static field initializers. The output shows that the blocks and fields are evaluated in execution order.

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'

请注意,超类的任何静态初始化都会先执行,然后再执行其子类。

¥Note that any static initialization of a super class is performed first, before that of its sub classes.

使用这个和超级

¥Using this and super

静态块内的 this 指的是该类的构造函数对象。此代码显示如何访问公共静态字段。

¥The this inside a static block refers to the constructor object of the class. This code shows how to access a public static field.

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

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

¥The super.property syntax can be used inside a static block to reference static properties of a super class.

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

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

进入私有属性

¥Access to private properties

下面的示例显示了如何从类外部的对象授予对类的私有实例字段的访问权限(来自 v8.dev 博客 的示例):

¥This example below shows how access can be granted to a private instance field of a class from an object outside the class (example from the 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'

规范

Specification
ECMAScript Language Specification
# prod-ClassStaticBlock

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看

¥See also