類靜態(tài)初始化塊即將納入ES2022,我們先一睹為快
Ron Buckton 提出的 ECMAScript 提案 "類靜態(tài)初始化塊"已進(jìn)入第四階段,計劃納入ECMAScript 2022。
為了建立一個類的實(shí)例,在JavaScript中有兩個結(jié)構(gòu):
字段:創(chuàng)建(可選擇初始化)實(shí)例屬性。
構(gòu)造函數(shù):在 setup 完成之前執(zhí)行的代碼塊。
對于類的靜態(tài)部分的設(shè)置,我們只有靜態(tài)字段。ECMAScript建議為類引入靜態(tài)初始化塊,大致上,它對靜態(tài)類的作用就像構(gòu)造函數(shù)對實(shí)例的作用。
1.為什么我們需要類中的靜態(tài)塊?
在設(shè)置靜態(tài)字段時,使用外部函數(shù)通常也可以很好地工作:
- 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);
- }
使用外部函數(shù) extractEnglish()和 extractGerman() 在這種情況下效果很好,因為我們可以看到它們是從類內(nèi)部調(diào)用的,而且它們完全獨(dú)立于類。
如果我們想同時設(shè)置兩個靜態(tài)字段,事情就變得不那么優(yōu)雅。
- 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);
- }
- }
這一次,有幾個問題。
- 調(diào)用initializeTranslator()是一個額外的步驟,要么在創(chuàng)建類之后,在類之外執(zhí)行。或者通過一個變通方法來執(zhí)行(A行)。
- initializeTranslator() 不能訪問 Translator 的私有數(shù)據(jù)。
通過提出的靜態(tài)塊(A行),我們有更優(yōu)雅的解決方案。
- 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.一個更復(fù)雜的例子
在JavaScript中實(shí)現(xiàn)枚舉的一種方法是通過帶有輔助功能的超類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'
我們需要收集靜態(tài)字段,以便我們可以遍歷枚舉項的鍵(B行)。這是在創(chuàng)建所有靜態(tài)字段之后的最后一步。我們再次使用一個變通方法(A行),靜態(tài)塊會更優(yōu)雅。
3.詳情
靜態(tài)塊的具體內(nèi)容相對來說是合乎邏輯的(相比之下,實(shí)例成員的規(guī)則更為復(fù)雜):
- 每個類可以有一個以上的靜態(tài)塊。
- 靜態(tài)塊的執(zhí)行是與靜態(tài)字段初始化器的執(zhí)行交錯進(jìn)行的。
- 超類的靜態(tài)成員在子類的靜態(tài)成員之前被執(zhí)行。
下面的代碼展示了這些規(guī)則:
- 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.在引擎中支持類靜態(tài)塊
- 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和/或一塌糊涂?
這是一個很小的功能,不會與其他功能競爭。我們已經(jīng)可以通過 static _ = ... 的字段來運(yùn)行靜態(tài)代碼。靜態(tài)塊意味著這種變通方法不再需要了。
除此之外,類只是JavaScript程序員腰帶上的眾多工具之一。我們中的一些人使用它,另一些人不使用它,而且有許多替代方案。即使是使用類的 JS 代碼,也經(jīng)常使用函數(shù),而且往往是輕量級的。
6.總結(jié)
類靜態(tài)塊是一個相對簡單的功能,它完善了類的靜態(tài)功能。粗略來說,它是實(shí)例構(gòu)造函數(shù)的靜態(tài)版本。它主要在我們需要設(shè)置一個以上的靜態(tài)字段時有用。
作者:Dr. Axel Rauschmayer 譯者:前端小智
來源:2ality 原文:https://2ality.com/2021/09/class-static-block.html