作者:Dr. Axel Rauschmayer
译者:前端小智
起源:2ality
有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq449245884/xiaozhi 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。
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.总结
类动态块是一个绝对简略的性能,它欠缺了类的动态性能。粗略来说,它是实例构造函数的动态版本。它次要在咱们须要设置一个以上的动态字段时有用。
~完,我是刷碗智,励志等退休后,要回家摆地摊的人,咱们下期见!
代码部署后可能存在的BUG没法实时晓得,预先为了解决这些BUG,花了大量的工夫进行log 调试,这边顺便给大家举荐一个好用的BUG监控工具 Fundebug。
原文:https://2ality.com/2021/09/cl...
交换
有幻想,有干货,微信搜寻 【大迁世界】 关注这个在凌晨还在刷碗的刷碗智。
本文 GitHub https://github.com/qq44924588... 已收录,有一线大厂面试残缺考点、材料以及我的系列文章。