使用 Array.prototype.with 的不可變更陣列更新

瀏覽器最近獲得了新的互通方法,您可以呼叫陣列:Array.prototype.with()

瀏覽器支援

  • 110
  • 110
  • 115
  • 16

來源

本文將探討這個方法的運作方式,以及如何在不變更原始陣列的情況下更新陣列。

Array.prototype.with(index, value) 簡介

Array.prototype.with(index, value) 方法會傳回函式呼叫的陣列副本,並將 index 設為您提供的新 value

以下範例顯示年齡陣列。您想要建立陣列的新副本,同時將第二個年齡從 15 變更為 16:

const ages = [10, 15, 20, 25];

const newAges = ages.with(1, 16);
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

細分程式碼:ages.with(...) 會傳回 ages 變數的副本,不會修改原始陣列。ages.with(1, …) 會取代第二個項目 (index = 1)。ages.with(1, 16) 會將第二個項目指派給 16

透過這種方式,您可透過修改的方式建立陣列的新副本。

如要確保原始陣列保持不變,這項功能就很實用,而本文將介紹一些相關用途。但就目前而言,看看您在使用括號標記法時的情形。

const ages = [10, 15, 20, 25];

const newAges = ages;
newAges[1] = 16;
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 16, 20, 25] (Also changed 🙁)

如您所見,在此範例中也修改了 ages 變數。這是因為指派 ages = newAges 時,JavaScript 不會複製陣列,而是建立另一個陣列的參照。因此,其中一項變更也會影響其他變更,因為兩者都指向同一個陣列。

Array.prototype.with() 和不變性

許多前端程式庫和架構的核心為不變動 包括 React (和 redux) 和 Vue

此外,其他程式庫和架構不一定需要不變性,但可以採取相應做法來提升效能:Angular 和 Lit

因此,開發人員經常必須使用其他方法來傳回陣列副本,以達到程式碼可讀性的目的:

const ages = [10, 15, 20, 25];

const newAges = ages.map((age, index) => {
    if (index === 1) {
         return 16;
    }
    return age;
});

console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (Remains unchanged)

以下範例程式碼說明如何在 React 中使用 .with() 與 useState,以不可變更的方式更新項目的陣列:

.with() 方法會傳回陣列的副本,因此您可以將多個 .with() 呼叫,甚至是其他陣列方法建立鏈結。以下範例說明如何增加陣列中的第二個和第三個年齡:

const ages = [10, 15, 20, 25];

const newAges = ages.with(1, ages[1] + 1).with(2, ages[2] + 1)

console.log(newAges); // [10, 16, 21, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

其他新的不可變動方法

最近還有另外三種方法可以互通:

這三種方法的根據 MDN 是其對應項目的複製版本。在預期或偏好的不變性時,這些方法也能使用。

總結來說,如果使用本文所述的四種方法,就能更輕鬆地在 JavaScript 中變更不可變更的更新。具體來說,.with() 方法可讓您在不變更原始陣列的情況下,輕鬆更新陣列的單一元素。