JavaScript(或ECMA Script) 是一門不斷發展的語言,有許多關於如何前進的建議和想法。TC39(技術委員會39)是負責定義JS標准和特性的委員會,今年他們非常活躍。以下是目前處於“Stage 3階段”的一些提案摘要,這是“完成”之前的最后一個階段。這意味着這些特性將很快在瀏覽器和其他引擎中實現。事實上,其中一些現在就有了。
1. 私有字段#
Chrome 和 NodeJS 12 已支持
是的,你沒看錯。JS終於在類中支持私有字段了。不再有 this._doPrivateStuff()
、定義閉包來存儲私有值或者使用WeakMap
來間接實現私有屬性。
語法是這樣的:
// 私有字段必須以 '#' 開頭
// and they can't be accessed outside the class block
class Counter {
#x = 0;
#increment() {
this.#x++;
}
onClick() {
this.#increment();
}
}
const c = new Counter();
c.onClick(); // 正常
c.#increment(); // 出錯
提案: https://github.com/tc39/proposal-class-fields
2. 可選鏈式調用 ?.
以往需要訪問嵌套在對象內部好幾層的屬性時,會得到臭名昭著的錯誤Cannot read property 'stop' of undefined
。然后你就要改變代碼來處理屬性鏈中每一個可能的undefined
對象,比如:
const stop = please && please.make && please.make.it && please.make.it.stop;
// 或者使用 'object-path' 這樣的庫
const stop = objectPath.get(please, "make.it.stop");
有了可選鏈式調用 ,你只要這樣寫就可以做同樣的事情:
const stop = please?.make?.it?.stop;
提案: https://github.com/tc39/proposal-optional-chaining
3. 空合並操作符 ??
變量的可選值可能沒有,如果沒有則使用默認值。這種情況很常見:
const duration = input.duration || 500;
使用||
的問題是,它會覆蓋所有的假值,如(0
, ''
, false
),這些值可能是在某些情況下有效的輸入。
輸入空合並操作符,它只覆蓋undefined
或null
。
const duration = input.duration ?? 500;
提案: https://github.com/tc39/proposal-nullish-coalescing
4. BigInt 1n
Chrome 和 NodeJS 12 已支持
JS在數學方面一直很糟糕的一個原因是,我們無法可靠地存儲大於2 ^ 53
的數字,這使得處理相當大的數字非常困難。幸運的是,BigInt
是解決這個特定問題的提案。
// 可以通過附加'n'到一個數字字面量來定義BitInt
const theBiggestInt = 9007199254740991n;
// 使用構造器
const alsoHuge = BigInt(9007199254740991);
// 或則字符串形式
const hugeButString = BigInt('9007199254740991');
你也可以在BigInt
上使用與普通數字相同的運算符,例如 +
, -
, /
, *
, %
等等。不過有一個問題,在大多數操作中,不能將 BigInt
與Number
混合使用。比較Number
和 BigInt
是可以的,但是不能把它們相加。
1n < 2
// true
1n + 2
// 🤷♀️ Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
提案: https://github.com/tc39/proposal-bigint
參考閱讀:一文搞懂JavaScript 新數據類型BigInt
5. static
字段
Chrome & NodeJS 12 已支持
這個很簡單。它允許類擁有靜態字段,類似於大多數OOP語言。靜態字段可以用來代替枚舉,也可以用於私有字段。
class Colors {
// public static 字段
static red = '#ff0000';
static green = '#00ff00';
// private static 字段
static #secretColor = '#f0f0f0';
}
font.color = Colors.red;
font.color = Colors.#secretColor; // Error
提案: https://github.com/tc39/proposal-static-class-features
6. 頂層 await
Chrome 已支持
允許您在代碼的頂層作用域使用await。這對於在瀏覽器控制台中調試異步內容(如 fetch
)非常有用,而不需要在異步函數中包裝它。
另一個殺手級用例是,它可以在用異步方式初始化的ES模塊的頂層使用(比如建立數據庫連接)。當這樣一個異步模塊被導入時,模塊系統將等待它解析,然后再執行依賴它的模塊。這將使處理異步初始化比目前通過返回一個初始化promise並等待它解決來得更容易。模塊將不知道它的依賴是否異步。
// db.mjs
export const connection = await createConnection();
// server.mjs
import { connection } from './db.mjs';
server.start();
在本例中,server.mjs
中不執行任何操作,直到在db.mjs
中完成連接。
提案:https://github.com/tc39/proposal-top-level-await
參考閱讀:頂層 await 釋疑
7. WeakRef
- Chrome 和 NodeJS 12 已支持*
對象的弱引用是不足以對象處於活動狀態的引用。當我們使用(const
, let
, var
)創建一個變量時,垃圾收集器(GC)將永遠不會從內存中刪除該變量,只要它的引用仍然是可訪問的。這些都是強引用。然而,弱引用引用的對象如果沒有強引用,則GC可以在任何時候刪除它。WeakRef
實例有一個方法deref
,它返回引用的原始對象,如果原始對象被回收,則返回undefined
。
這對於緩存廉價對象可能很有用,因為你不想將所有對象都永遠存儲在內存中。
const cache = new Map();
const setValue = (key, obj) => {
cache.set(key, new WeakRef(obj));
};
const getValue = (key) => {
const ref = cache.get(key);
if (ref) {
return ref.deref();
}
};
const fibonacciCached = (number) => {
const cached = getValue(number);
if (cached) return cached;
const sum = calculateFibonacci(number);
setValue(number, sum);
return sum;
};
對於緩存遠程數據來說,這可能不是一個好主意,因為遠程數據可能會不可預測地從內存中刪除。在這種情況下,最好使用LRU之類的緩存。
提案:https://github.com/tc39/proposal-weakrefs
以上。希望你和我一樣對使用這些很酷的新功能感到興奮。要了解更多關於這些提案和其他我沒有提到的細節,請關注github上的TC39提案
原文:7 Exciting New JavaScript Features You Need to Know
交流
歡迎關注微信公眾號“1024譯站”,跟我一起關注最新技術趨勢。