ES——ES2020&2021

巴伐利亚药水哥發表於2024-08-14

一、規範

1、for-in 機制

ECMA-262 規範沒有規定 for (a in b) ... 的遍歷順序,部分原因是所有引擎都有自己特殊的實現,現在很難就 for-in 完整順序規範達成一致,但規範了一些供參考的實現行為,詳情參考 this list of interop semantics。

二、方法

1、matchAll - 匹配所有

String.prototype.matchAll() 會返回正則匹配的所有字串及其位置,相比於 String.prototype.match() 返回的資訊更詳細。

const str = 'JavaScript'
const regexp = /a/g
console.log([...str.matchAll(regexp)]);

// Output:
[
  [ 'a', index: 1, input: 'JavaScript', groups: undefined ],
  [ 'a', index: 3, input: 'JavaScript', groups: undefined ]
]

2、模組新特性

  • import 動態匯入

動態匯入意思是當你需要該模組時才會進行載入,返回的是一個 Promise 物件。只有在 ES Modules 模組規範下才支援。

// index-a.mjs
export default {
  hello () {
    console.log(`hello JavaScript`);
  }
}

// index-b.mjs
import('./index-a.mjs').then(module => {
  module.default.hello(); // hello JavaScript
})

  • import.meta

import.meta 指當前模組的後設資料。一個廣泛支援的屬性是 import.meta.url,以字串形式輸出當前模組的檔案路徑。

3、BigInt

BigInt 是新增的一種描述資料的型別,用來表示任意大的整數。因為原先的 JavaScript Number 型別能夠表示的最大整數位 Math.pow(2, 53) - 1,一旦超出就會出現精度丟失問題。詳情可參考筆者之前的這篇文章 JavaScript 浮點數之迷下:大數危機 https://github.com/qufei1993/blog/issues/10。

9007199254740995 // 會出現精度丟失
9007199254740995n // BigInt 表示方式一
BigInt('9007199254740995') // BigInt 表示方式二

4、Promise.allSettled

Promise.allSettled() 會等待所有的 Promise 物件都結束後在返回結果。

const delay = (value, ms, isReject) => new Promise(
    (resolve, reject) => setTimeout(
        () => isReject ? reject(new Error(value)) : resolve(value)
        , ms
    )
);
const promises = [
    delay('a', 3000),
    delay('b', 2000, true),
];
Promise.allSettled(promises)
    .then(res => console.log(res))

// Output:
// [
//     { status: 'fulfilled', value: 'a' },
//     {
//         status: 'rejected',
//         reason: Error: b
//         at Timeout._onTimeout(/index.js:1:108)
//         at listOnTimeout(node: internal / timers: 564: 17)
//         at process.processTimers(node: internal / timers: 507: 7)
//   }
// ]

5、全域性物件

JavaScript 可以執行在不同的環境,瀏覽器為 window、Node.js 為 global。為了能夠統一全域性環境變數,引入了 globalThis。

window === globalThis // 瀏覽器環境
global === globalThis // Node.js 環境

6、可選鏈

可選鏈是一個很好的語法,使用 ?. 表示,能避免一些常見型別錯誤。

const obj = null;
obj.a // TypeError: Cannot read properties of null (reading 'a')
obj?.a // 使用可選鏈之後就不會報錯了,會輸出 undefined

7、空值合併

空值合併語法使用 ?? 表示,和 || 這個語法類似,不同的是 ?? 有明確的規定,只有當左側的值為 null 或 undefined 時才會返回右側的值,例如,左側是 0 也會認為是合法的。

const a = 0
a || 1 // 1
a ?? 1 // 0

8、String.prototype.replaceAll

replaceAll() 用於替換正規表示式或字串的所有匹配項,之前的 replace() 只會匹配一個。

console.log('JavaScript'.replaceAll('a', 'b')); // JbvbScript

9、Promise.any

Promise.any() 接收一個 Promise 陣列做為引數,返回第一個執行成功的 Promise,如果全部執行失敗將返回一個新的異常型別 AggregateError,錯誤資訊會以物件陣列的形式放入其中。

const delay = (value, ms) => new Promise((resolve, reject) => setTimeout(() => resolve(value), ms));
const promises = [
  delay('a', 3000),
  delay('b', 2000),
  delay('c', 4000),
];

Promise.any(promises)
  .then(res => console.log(res)) // b
  .catch(err => console.error(err.name, err.message, err.errors)) // 全部失敗時返回:AggregateError All promises were rejected [ 'a', 'b', 'c' ]

10、數字分隔符

數字分隔符可以讓大數字看起來也容易理解。

const budget = 1_000_000_000_000;
console.log(budget === 10 ** 12); // true

11、邏輯賦值運算子

結合了邏輯運算子 &&||?? 和邏輯表示式 =

// "Or Or Equals" (or, the Mallet operator :wink:)
a ||= b; // a || (a = b);

// "And And Equals"
a &&= b; // a && (a = b);

// "QQ Equals"
a ??= b; // a ?? (a = b);

12、WeakRefs

能夠拿到一個物件的弱引用,而不會阻止該物件被垃圾回收。例如 ref 弱引用了 obj,儘管持有了 obj 物件的引用,但也不會阻止垃圾回收 obj 這個物件,如果是強引用則不行。 參考 https://github.com/tc39/proposal-weakrefs

const obj = { a: 1 };
const ref = new WeakRef(obj)
console.log(ref.deref());