ECMAScript 2020(ES11)新特性簡介
- 2021 年 8 月 5 日
- 筆記
- es11, es2020, javascript
簡介
ES2020
是ECMA協會在2020年6月發行的一個版本,因為是ECMAScript的第十一個版本,所以也稱為ES11.
今天我們講解一下ES11的新特性。
ES11引入了9個新特性,我們接下來一一講解。
動態imports
在ES11之前,我們可以使用下面的方式進行模組的導入:
import * as TestModule from "./test-module.js";
導入模組的現有語法形式為靜態聲明。它們接受字元串字面作為模組標識符,並通過運行前”鏈接”過程將綁定引入本地範圍。可能會導致程式載入速度的降低。而且上面的模組名字是寫死的,不可以在程式運行的時候進行動態修改。
為了解決這個問題,ES11引入了新的import()
方法,使用這個方法,你可以對模組進行動態導入,並且通過設置模組名為變數的形式,可以對模組名進行動態修改,非常的神奇。我們看一個具體的使用例子:
const baseModulePath = "./baseModules";
const btn = document.getElementById("btn");
let userList = [];
btn.addEventListener("click", async () => {
const userModule = await import(`${baseModulePath}/users.js`);
userList = userModule.getUserList();
});
上面程式碼中我們定義了一個基本的Module路徑,通過點擊頁面上的按鈕,可以動態的載入一個users.js
模組,然後調用該模組的getUserList()
方法,獲得用戶列表。
import.meta
除了動態引入模組之外,import還提供了一個元屬性meta
,它包含了當前引入的模組的資訊,目前他裡面有一個url屬性,代表模組被引用的URL。如果想使用URL資訊,那麼可以在程式碼中使用import.meta.url
。
BigInt
ES11引入了新的數據類型BigInt
,在這之前,javascript
中表示數字的對象是Number
,它可以表示64-bit
的浮點類型數字。當然它也可以代表整數,但是整數表示的最大值是2^53
,也可以用Number.MAX_SAFE_INTEGER
來表示。
一般來說Number已經夠用了,但是如果在某些情況下需要對64-bit的整數進行存儲或者運算,或者要表示的範圍超過了64-bit的話,Number就不夠用了。
怎麼辦呢?如果只是存儲的話,可以存儲為字元串,但是第二種字元串就不適用了。於是引入了BigInt來解決這個問題。要表示BigInt,只需要在數字的後面加上n即可。
const bigInt1 = 112233445566778899n;
const bigInt2 = BigInt("112233445566778899");
可以使用typeof
來查看bigInt
的類型。要注意的是雖然Number
和BigInt
都代表的是數字,但是兩者是不能混用的,你不能將一個Number
和一個BigInt
相加。這會報TypeError
異常。
如果非要進行操作,那麼可以使用BigInt構造函數將Number轉換成為BigInt之後再進行。
String.prototype.matchAll()
matchAll
是match
的增強版,match
返回匹配的結果,matchAll
返回更加詳細的匹配結果
const str = 'abcdefga';
const reg = /a/g
const result1 = str.matchAll(reg);
/*
* result1
* ['a','a']
*/
const result2 = str.matchAll(reg);
/*
* result2
* [
* [ 'a', index: 0, input: 'abcdefga', groups: undefined ],
* [ 'a', index: 7, input: 'abcdefga', groups: undefined ]
* ]
*/
globalThis
對於javascript來說,不同的環境對應的全局對象的獲取方式也是不同的,對於瀏覽器來說通常使用的是window
,但是在web worker中使用的是self
,而在nodejs中使用的是global
。
為了解決在不同環境中的全局對象不同的問題,ES11
引入了globalThis
,通過這個全局對象,程式設計師就不用再去區分到底是在哪個環境下了,只需要使用globalThis即可。
Promise.allSettled()
自從Promise引入之後,有兩個方法可以對Promise進行組合,分別是Promise.all()
和Promise.race()
。
Promise.race()
:只要有一個resolve
就返回(返回最快執行的那個)Promise.all()
:它會等待所有的Promise
都運行完畢之後返回,如果其中有一個Promise
被rejected
,那麼整個Promise.all()
都會被rejected
。在這種情況下,如果有一個Promise被rejected,其他的Promise的結果也都獲取不了。Promise.allSettled()
: 這個方法會等待所有的Promise
結束,不管他們是否被rejected
,所以可以獲得所有的結果。
const promises = [ fetch('index.html'), fetch('//does-not-exist/') ];
const results = await Promise.allSettled(promises);
const errors = results
.filter(p => p.status === 'rejected')
.map(p => p.reason);
??
空值合併運算符
??
操作符是一個判斷是否為空然後賦值的操作,如果沒有這個操作符,我們通常使用||來簡單的進行這個操作,如下所示:
const person = {
name: 'Tom',
age: 18,
}
const yourAge = person.age || 18;
上面的程式碼意思是如果person.age
是空,那麼就將yourAge
設置成為18
。
但是上面程式碼有個問題,如果someBody.age=0 的話,上述邏輯也成立。使用??
操作符可以解決這個問題。
const person = {
name: 'Tom',
age: 18,
}
const yourAge = person.age ?? 18;
?.
可選鏈操作符
我們有時候在獲取某個對象的屬性的時候,需要進行對象的null判斷,否則從null對象中取出屬性就會報錯,但是通常的?:操作符使用起來太複雜了,如果有多個對象和屬性連寫的情況下更是如此,如果使用?.操作符就會簡單很多:
const person = {
name: 'Tom',
age: 18,
}
const age = person?.age;
如上所示,這個一個連寫操作,但是使用?.
就變得很簡單。
同樣?.
還可以用在對象的方法上:
const person = {
name: 'Tom',
age: 18,
getAge(){
return person.age;
}
}
const age = student.getAge?.();
上面程式碼表示,如果person
的getAge
方法存在,則調用,否則返回undefined
。
for-in
ECMAScript 遺留了 for-in
循環順序的詳盡介紹待填補。在ES2020中為 for-in
機制定義了一套規則。
參考
proposals/finished-proposals.md at master · tc39/proposals (github.com)