前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >类静态初始化块即将纳入ES2022,我们先一睹为快

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

作者头像
前端小智@大迁世界
发布2022-06-15 15:07:18
1760
发布2022-06-15 15:07:18
举报
文章被收录于专栏:终身学习者终身学习者

作者:Dr. Axel Rauschmayer 译者:前端小智 来源:2ality

本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

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

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

  • 字段:创建(可选择初始化)实例属性。
  • 构造函数:在 setup 完成之前执行的代码块。

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

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

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

代码语言:javascript
复制
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() 在这种情况下效果很好,因为我们可以看到它们是从类内部调用的,而且它们完全独立于类。

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

代码语言:javascript
复制
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行),我们有更优雅的解决方案。

代码语言:javascript
复制
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

代码语言:javascript
复制
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.详情

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

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

下面的代码展示了这些规则:

代码语言:javascript
复制
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.总结

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

~完,我是刷碗智,励志等退休后,要回家摆地摊的人,我们下期见!


代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug

原文:https://2ality.com/2021/09/cl...

交流

本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试完整考点、资料以及我的系列文章。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2022-06-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.为什么我们需要类中的静态块?
  • 2.一个更复杂的例子
  • 3.详情
  • 4.在引擎中支持类静态块
  • 5.JS 是否变得太像Java和/或一塌糊涂?
  • 6.总结
  • 交流
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档