◆ 配列の破壊的メソッドの非破壊的版メソッドが追加された
  ◆ sort → toSorted, splice → toSpliced, reverse → toReversed
◆ インデックス指定で書き換えた版の with が追加された
◆ slice の手間が省けたくらいだけど with はメソッドチェーンで書けるので便利
◆ with は存在しないインデックスを指定するとエラーが起きるので場合によっては使えない

この機能です
https://github.com/tc39/proposal-change-array-by-copy

Chrome 109 だと動かなくて 110 に更新したら動くようになったので 110 で追加のはずなのに Chrome Status では情報がないです
https://chromestatus.com/features#milestone%3D110

110 の更新内容には含まれてなくて 機能ごとの詳細ページを見ても 108 で DevTrial とだけ書かれていて Ship のバージョン情報がないです
https://chromestatus.com/feature/5068609911521280

ときどきこういうのがありますが Chrome Status のサイトの情報はあまり更新されてないのでしょうか
個別にバグトラッカーのサイトまで見るのは面倒なのでここにまとまっていてほしいです

追加された配列メソッド

追加された機能は 配列の破壊的メソッドに非破壊的メソッドが追加されたというものです
sort, reverse, splice はその配列自体を変更してしまうので 元を保持したいなら slice などでコピーする必要がありました
これらにコピー不要で新しい配列を作る版のメソッドが増えました

const arr = [1, 2, 3]
console.log(arr.toSorted((a, b) => b - a))
// [3, 2, 1]
console.log(arr)
// [1, 2, 3]
const arr = [1, 2, 3]
console.log(arr.toReversed())
// [3, 2, 1]
console.log(arr)
// [1, 2, 3]
const arr = [1, 2, 3]
console.log(arr.toSpliced(1, 1, 4, 5))
// [1, 4, 5, 3]
console.log(arr)
// [1, 2, 3]

また 直接インデックス指定で書き換えの新しい配列を作る版の with も追加されています

const arr = [1, 2, 3]
console.log(a.with(1, 100))
// [1, 100, 3]
console.log(arr)
// [1, 2, 3]

比較

これまででも

arr.slice().sort()
arr.slice().reverse()

みたいにメソッドチェーンで書けて .slice() を挟むだけだったのであえて入れる必要ある?と思う内容でしたが toSpliced と with は一手間必要だったので嬉しい追加機能です

splice は sort や reverse と違って変更された配列と返り値は一致しません
変更したときに削除された要素の配列が返ってきます
toSpliced では変更された配列の方が返ってくるので toSpliced 相当のものが欲しい場合は一時変数に入れて配列の方を取得する必要があります

const arr2 = arr.slice()
arr2.splice(1, 1, 100)
console.log(arr2)

with は toSpliced でカバーできてる機能ですが よりわかりやすくかけます
これまでの方法でやろうとすると

arr.map((value, index) => index === 1 ? 100 : value)



const copy = arr.slice()
copy[1] = 100

みたいに少し読みづらい map をするか一時変数が必要になっていたのでこれをスッキリ書けるのは助かります
できればオブジェクトでも with メソッドを追加してほしいですが オブジェクトへのメソッド追加は影響が大きいのとスプレッド構文で十分とも言えるのでされない気がしますね

const obj = { a: 1, b: 2}
const obj2 = obj.with("a", 100)
const obj3 = { ...obj, a: 100 }

展開する部分の式が長くなるとチェーンに含められる方が見やすい気はしますけど

あとネストに対応して 深い部分のプロパティを変更したら全体の新しいオブジェクトを取得できるなら価値はありそうですが 実現はされなそうですね

他の破壊的メソッド

どうせなら push, shift, fill なども非破壊的メソッドを追加して toPushed, toShifted, toFilled などがあるとよかったのですけどね
軽く issue を見た感じ議論には出てそうだったので なにかの理由で通らなかったのでしょう
実際 concat や slice で代替できて 作るならこんな感じで簡単に作れるものですからね

Array.prototype.toPushed = function(...args) { return [...this, ...args] }
Array.prototype.toPopped = function() { return this.slice(0, -1) }
Array.prototype.toUnshifted = function(...args) { return [...args, ...this] }
Array.prototype.toShifted = function() { return this.slice(1) }
Array.prototype.toFilled = function(value) { return this.map(() => value) }

でもそれをいえば sort だって .slice() 挟むだけなんですけどね

push や pop は返す値が配列の長さや取り出されたものなので 変更後の配列を返すのは目的が変わってしまうとかあるのかな と思いましたが splice は取り出された配列を return するのに toSpliced では取り出された配列は取得できず変更後の配列を返してます
そう考えるとやっぱり toPushed とかはあってもいいのではと思います

with の不便なところ

まとめて変更できない

1 つの with で値を一つしか変更できないです
この手の API だとライブラリではオブジェクトで渡せば複数を一気に変更できそうなものですができません

arr.with({ 1: 100, 2: 200 })

みたいなことは無効です

arr.with(1, 100).with(2, 200)

のようにひとつずつ変更が必要です
ただ with ごとに内部的にはコピーが作られるわけで 要素数の多い配列で多くの with を繰り返すのは無駄が多くパフォーマンスに影響しそうです

値があるインデックスしか指定できない

値のないインデックスを指定するとエラーが起きます

const arr = [1, 2, 3]
arr.with(5, 100)
// Uncaught RangeError: Invalid index : 5

slice でコピーして直接代入する方法だとこういうエラーは起きないのでこういう制限があるのは不便です
インデックスの範囲を超えていても気にしないのが JavaScript らしさだと思うのですが こういうのをエラーにされても不便なだけです
その割にインデックスに文字列など不正な数値を渡してもエラーにはならず 0 として処理されるのでこの辺はゆるいままです

const arr = [1, 2, 3]
arr.with("foo", 100)
// [100, 2, 3]

内部で map を使う方法を呼び出してるとかで長さを変えることができないのでしょうか?
それでもエラーにされるよりは map を使うときの結果と同じように一致するのがないなら置き換えなしでただのコピーとしてくれたほうがいいのですけど