ES——ES2022+

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

ES2023

ES2023 新特性目前有兩條:Array find from last、Hashbang Grammar,也都處於 stage 4 階段,預計 2023 年釋出。

從陣列末尾查詢元素

新增兩個方法: .findLast().findLastIndex() 從陣列的最後一個元素開始查詢,可以同 find()findIndex() 做一個對比。

const arr = [{ value: 1 }, { value: 2 }, { value: 3 }, { value: 4 }];

// find vs findLast
console.log(arr.find(n => n.value % 2 === 1)); // { value: 1 }
console.log(arr.findLast(n => n.value % 2 === 1)); // { value: 3 }

// findIndex vs findLastIndex
console.log(arr.findIndex(n => n.value % 2 === 1)); // 0
console.log(arr.findLastIndex(n => n.value % 2 === 1)); // 2

Hashbang 語法

如下所示,在 index.js 指令碼檔案裡編寫 JS 程式碼,如果要正確的執行,需要在控制檯輸入 node index.js

console.log("JavaScript");

如果直接執行 ./index.js 指令碼檔案會得到以下報錯:

$ ./index.js
./index.js: line 1: syntax error near unexpected token `"JavaScript"'
./index.js: line 1: `console.log("JavaScript");'

很正常,因為我們並沒有指定使用何種直譯器來執行上述指令碼檔案。Hashbang 語法是用來指定指令碼檔案的直譯器是什麼,語法規則是在指令碼檔案頭部增加一行程式碼:#!/usr/bin/env node

// #!/usr/bin/env node
console.log("JavaScript");

注意,還需修改指令碼檔案的許可權 chmod +x index.js,否則執行會報 permission denied: ./index.js 錯誤。

ES2022

Class Fields

允許在類最外層宣告類成員,參考 https://github.com/tc39/proposal-class-fields。

class Person {
  name = 'Tom'
}

私有化類成員:支援私有例項、私有靜態型別欄位、私有方法。

class Person {
  #privateField1 = 'private field 1'; // 私有欄位賦初值
  #privateField2; // 預設 undefined
  static #privateStaticField3 = 'private static field 3'
  constructor(value) {
    this.#privateField2 = value; // 例項化時為私有欄位賦值
  }
  #toString() {
    console.log(this.#privateField1, this.#privateField2, InstPrivateClass.#privateStaticField3);
  }
  print() {
    this.#toString()
  }
}
const p = new Person('private field 2')
p.print()

私有欄位檢查

使用 in 運算子檢測某一例項是否包含要檢測的私有欄位。

class Person {
  #name = 'Ergonomic brand checks for Private Fields';
  static check(obj) {
    return #name in obj;
  }
}

Top-level await

以前 await 必須隨著 async 一起出現,只有在 async 函式內才可用。當需要在一些檔案頂部進行初始化的場景中使用時就有不支援了,頂級 await 可以解決這個問題,但它僅支援 ES Modules。

let jQuery;
try {
  jQuery = await import('https://cdn-a.com/jQuery');
} catch {
  jQuery = await import('https://cdn-b.com/jQuery');
}

正則新增 /d 修飾符

以前的正規表示式支援 3 個修飾符:/i(忽略大小寫)、/g(全域性匹配)、/m(多行),當執行正規表示式的 exec() 方法時,新增一個 /d 修飾符,它會返回一個 indices 屬性,包含了匹配元素的開始、結束位置索引。

const str = 'ECMAScript_JavaScript'
const regexp = /sc/igd // 忽略大小全域性匹配並返回匹配元素的開始、結束位置索引
console.log(regexp.exec(str).indices) // [ 4, 6 ]
console.log(regexp.exec(str).indices) // [ 15, 17 ]

.at() 運算子

根據指定索引獲取陣列元素,不同的是它支援傳遞負數,例如 -1 獲取最後一個元素。

const arr = ['a', 'b', 'c']
console.log(arr.at(0));
console.log(arr.at(-1)); // 等價於 arr[arr.length - 1]

Object.hasOwn()

Object.hasOwn() 提供了一種更安全的方法來檢查物件是否具有自己的屬性,適用於檢查所有的物件。Object.prototype.hasOwnProperty() 方法遇到 obj = null這種情況會報錯,參見以下示例:

const person = Object.create({ name: 'Tom' })
person.age = 18;
console.log(Object.hasOwn(person, 'name')); // false
console.log(Object.hasOwn(person, 'age')); // true

// 遇到這種情況 hasOwnProperty 會報錯
const p1 = null
console.log(p1.hasOwnProperty('name')); // TypeError: Cannot read properties of null (reading 'hasOwnProperty')

Error Cause

Error Cause 是由阿里巴巴提出的一個提案,為 Error 建構函式增加了一個 options,可設定 cause 的值為任意一個有效的 JavaScript 值。

例如,自定義錯誤 message,將錯誤原因賦給 cause 屬性,傳遞給下一個捕獲的地方。

try {
  await fetch().catch(err => {
    throw new Error('Request failed', { cause: err })
  })
} catch (e) {
  console.log(e.message);
  console.log(e.cause);
}

Class Static Block

類的靜態初始化塊是在類中為靜態成員提供了一個用於做初始化工作的程式碼塊。

class C {
  static x = 'x';
  static y;
  static z;
  static {
    try {
      const obj = doSomethingWith(this.x);
      this.y = obj.y;
      this.z = obj.z;
    } catch (err) {
      this.y = 'y is error';
      this.z = 'z is error';
    }
  }
}