類靜態初始化塊即將納入ES2022,我們先一睹為快

前端小智發表於2021-11-30
作者: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... 已收錄,有一線大廠面試完整考點、資料以及我的系列文章。

相關文章