类静态初始化块即将纳入ES2022,我们先一睹为快
作者:Dr. Axel Rauschmayer
译者:前端小智
来源:2ality
有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。Ron Buckton 提出的 ECMAScript 提案 "类静态初始化块"已进入第四阶段,计划纳入ECMAScript 2022。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
为了建立一个类的实例,在JavaScript中有两个结构:
- 字段:创建(可选择初始化)实例属性。
- 构造函数:在 setup 完成之前执行的代码块。
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
的私有数据。
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)
这是一个很小的功能,不会与其他功能竞争。我们已经可以通过
static _ = ...
的字段来运行静态代码。静态块意味着这种变通方法不再需要了。除此之外,类只是JavaScript程序员腰带上的众多工具之一。我们中的一些人使用它,另一些人不使用它,而且有许多替代方案。即使是使用类的 JS 代码,也经常使用函数,而且往往是轻量级的。
6.总结
类静态块是一个相对简单的功能,它完善了类的静态功能。粗略来说,它是实例构造函数的静态版本。它主要在我们需要设置一个以上的静态字段时有用。
~完,我是刷碗智,励志等退休后,要回家摆地摊的人,我们下期见!
代码部署后可能存在的BUG没法实时知道,事后为了解决这些BUG,花了大量的时间进行log 调试,这边顺便给大家推荐一个好用的BUG监控工具 Fundebug。
原文:https://2ality.com/2021/09/cl...
交流
有梦想,有干货,微信搜索 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。【类静态初始化块即将纳入ES2022,我们先一睹为快】
本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试完整考点、资料以及我的系列文章。
文章图片
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- parallels|parallels desktop 解决网络初始化失败问题
- 为什么你的路演总会超时()
- 标签、语法规范、内联框架、超链接、CSS的编写位置、CSS语法、开发工具、块和内联、常用选择器、后代元素选择器、伪类、伪元素。
- thinkphp|thinkphp 3.2 如何调用第三方类库
- 使用composer自动加载类文件
- 一个健康的APP和健全的人格大体类似
- 种树郭橐驼传(文言句式+古今异义+词类活用+通假字)
- 归乡-序章(世界伊始,人类无所依靠,我的故事就从这里开始...)
- jQuery插件