您现在的位置是:亿华云 > 域名

类静态初始化块即将纳入ES2022,我们先一睹为快

亿华云2025-10-03 19:56:01【域名】5人已围观

简介Ron Buckton 提出的 ECMAScript 提案 "类静态初始化块"已进入第四阶段,计划纳入ECMAScript 2022。为了建立一个类的实例,在JavaScript中有两个结构:字段:创

Ron Buckton 提出的类静 ECMAScript 提案 "类静态初始化块"已进入第四阶段,计划纳入ECMAScript 2022。态初

为了建立一个类的始化实例,在JavaScript中有两个结构:

字段:创建(可选择初始化)实例属性。

构造函数:在 setup 完成之前执行的块即代码块。

对于类的将纳静态部分的设置,我们只有静态字段。先睹ECMAScript建议为类引入静态初始化块,为快大致上,类静它对静态类的态初作用就像构造函数对实例的作用。

1.为什么我们需要类中的始化静态块?

在设置静态字段时,使用外部函数通常也可以很好地工作:

class Translator {    static translations = {      yes: ja,块即     no: nein,     maybe: vielleicht,   };   static englishWords = extractEnglish(this.translations);   static germanWords = extractGerman(this.translations); } function extractEnglish(translations) {    return Object.keys(translations); } function extractGerman(translations) {    return Object.values(translations); } 

使用外部函数 extractEnglish()和 extractGerman() 在这种情况下效果很好,因为我们可以看到它们是将纳从类内部调用的,而且它们完全独立于类。先睹

如果我们想同时设置两个静态字段,为快事情就变得不那么优雅。类静

class Translator {    static translations = {      yes: ja,     no: nein,     maybe: vielleicht,   };   static englishWords = [];   static germanWords = [];   static _ = initializeTranslator( // (A)     this.translations, this.englishWords, this.germanWords); } function initializeTranslator(translations, englishWords, germanWords) {    for (const [english, german] of Object.entries(translations)) {      englishWords.push(english);     germanWords.push(german);   } } 

这一次,有几个问题。

调用initializeTranslator()是一个额外的步骤,要么在创建类之后,在类之外执行。或者通过一个变通方法来执行(A行)。 initializeTranslator() 不能访问 Translator 的服务器租用私有数据。

通过提出的静态块(A行),我们有更优雅的解决方案。

class Translator {    static translations = {      yes: ja,     no: nein,     maybe: vielleicht,   };   static englishWords = [];   static germanWords = [];   static {  // (A)     for (const [english, german] of Object.entries(this.translations)) {        this.englishWords.push(english);       this.germanWords.push(german);     }   } } 

2.一个更复杂的例子

在JavaScript中实现枚举的一种方法是通过带有辅助功能的超类Enum

class Enum {    static collectStaticFields() {      // Static methods are not enumerable and thus ignored     this.enumKeys = Object.keys(this);   } } class ColorEnum extends Enum {    static red = Symbol(red);   static green = Symbol(green);   static blue = Symbol(blue);   static _ = this.collectStaticFields(); // (A)   static logColors() {      for (const enumKey of this.enumKeys) {  // (B)       console.log(enumKey);     }   } } ColorEnum.logColors(); // Output: // red // green // blue 

我们需要收集静态字段,以便我们可以遍历枚举项的键(B行)。这是在创建所有静态字段之后的最后一步。我们再次使用一个变通方法(A行),静态块会更优雅。

3.详情

静态块的具体内容相对来说是合乎逻辑的(相比之下,实例成员的规则更为复杂):

每个类可以有一个以上的静态块。 静态块的执行是与静态字段初始化器的执行交错进行的。 超类的静态成员在子类的静态成员之前被执行。

下面的服务器托管代码展示了这些规则:

class SuperClass {    static superField1 = console.log(superField1);   static {      assert.equal(this, SuperClass);     console.log(static block 1 SuperClass);   }   static superField2 = console.log(superField2);   static {      console.log(static block 2 SuperClass);   } } class SubClass extends SuperClass {    static subField1 = console.log(subField1);   static {      assert.equal(this, SubClass);     console.log(static block 1 SubClass);   }   static subField2 = console.log(subField2);   static {      console.log(static block 2 SubClass);   } } // Output: // superField1 // static block 1 SuperClass // superField2 // static block 2 SuperClass // subField1 // static block 1 SubClass // subField2 // static block 2 SubClass 

4.在引擎中支持类静态块

V8: unflagged in v9.4.146 (source) SpiderMonkey: behind a flag in v92, intent to ship unflagged in v93 (source) TypeScript: v4.4 (source)

5.JS 是否变得太像Java和/或一塌糊涂?

这是一个很小的功能,不会与其他功能竞争。我们已经可以通过 static _ = ... 的字段来运行静态代码。静态块意味着这种变通方法不再需要了。

除此之外,类只是JavaScript程序员腰带上的众多工具之一。我们中的一些人使用它,另一些人不使用它,而且有许多替代方案。即使是使用类的 JS 代码,也经常使用函数,而且往往是轻量级的。

6.总结

类静态块是一个相对简单的功能,它完善了类的静态功能。粗略来说,它是实例构造函数的静态版本。它主要在我们需要设置一个以上的站群服务器静态字段时有用。

作者:Dr. Axel Rauschmayer 译者:前端小智

来源:2ality 原文:https://2ality.com/2021/09/class-static-block.html

很赞哦!(39)