Array.prototype.with による不変の配列の更新

最近、ブラウザに配列で呼び出すことができる相互運用可能な新しいメソッド Array.prototype.with() が追加されました。

Browser Support

  • Chrome: 110.
  • Edge: 110.
  • Firefox: 115.
  • Safari: 16.

Source

この記事では、このメソッドの仕組みと、元の配列を変更せずに配列を更新する方法について説明します。

Array.prototype.with(index, value) の概要

Array.prototype.with(index, value) メソッドは、呼び出し元の配列のコピーを返します。このコピーでは、index が指定した新しい value に設定されています。

次の例は、年齢の配列を示しています。2 番目の年齢を 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, …) は 2 番目のアイテム(index = 1)を置き換えます。ages.with(1, 16) は 2 番目のアイテムを 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)

.with() を React で useState と組み合わせて使用し、アイテムの配列を不変的に更新する方法の Codepen の例を次に示します。

.with() メソッドは配列のコピーを返すため、複数の .with() 呼び出しや他の配列メソッドをチェーンできます。次の例は、配列から 2 番目と 3 番目の年齢を増やす方法を示しています。

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)

その他の新しい不変メソッド

最近、次の 3 つのメソッドが相互運用可能になりました。

MDN によると、これらの 3 つのメソッドは、対応するメソッドのコピー バージョンです。これらのメソッドは、不変性が期待される場合や推奨される場合にも使用できます。

結論として、この投稿で紹介した 4 つの方法のいずれかを使用すると、JavaScript で不変の更新をより簡単に実現できます。具体的には、.with() メソッドを使用すると、元の配列を変更せずに配列の単一の要素を簡単に更新できます。