かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

ES2023 JavaScript 配列から特定の要素を削除するのに toSpliced が便利

フロントエンドでやることはだいたい配列の操作だと感じてます。
その中でも元の配列を非破壊に特定のインデックスの要素を配列から削除するのが意外と面倒でした

今まで方法

1. filter で削除する要素を取り除く

const result = array.filter((item) => item.id !== deleteID);

この方法は非破壊に要素を削除した配列を削除できるが、配列を全て捜査する分処理が無駄になる

2. 削除する index を探して slice で取り除く

const deleteIndex = array.findIndex((item) => item.id === deleteID);
const result = [
  ...array.slice(0, deleteIndex),
  ...array.slice(deleteIndex + 1)
];

削除する要素の index を見つけるまで配列を捜査して、slice で配列から削除する要素を除いた配列を作成する方法
slice で index の要素を削除した配列を作成するコードが若干見通しが悪い

3. 配列を先にコピーして splice で要素を削除する

const deleteIndex = array.findIndex((item) => item.id === deleteID);
const copyArray = […array];
// or const Array = structuredClone(array); (deep copy)
copyArray.splice(deleteIndex, 1);
const result = copyArray;

.splice(deleteIndex, 1) で特定の index の要素を削除できるが、splice() は元の配列を変更してしまう破壊メソッドなので、先に配列を スプレッド構文 (Shallow copy)structuredClone (Deep copy) コピーしておく必要がある

toSpliced() メソッド

toSpliced() は Array インスタンスのメソッドで、 splice() メソッドに対応するコピーメソッドです。これは、指定された位置の要素を除去したり置き換えたりした新しい配列を返します。
cf. Array.prototype.toSpliced() - JavaScript | MDN

toSpliced() メソッドは splice() メソッドでできる配列の要素の削除・追加・置き換えを非破壊的にでき、新しい配列を返してくれる

const deleteIndex = array.findIndex((item) => item.id === deleteID);
const result = array.toSpliced(deleteIndex, 1);

従来の方法の 2, 3 を合わせてシンプルにしたように書ける!

Tips toSpliced()splice() の挙動の違い

splice() を使うことはあまりないと思いますが、破壊/非破壊だけでなく返り値に違いがあるので注意が必要です

  • toSpliced() は元の配列を変化させない (非破壊)・新しい配列を返す
  • splice() は元の配列を変化させる (破壊)・削除した要素の配列を返す
Sample

要素の削除

// toSpliced
const a1 = [1, 2, 3, 4, 5];
const res1 = a1.toSpliced(1, 2);

console.log(a1);   // [1, 2, 3, 4, 5]
console.log(res1); // [1, 4, 5]

// splice
const a2 = [1, 2, 3, 4, 5];
const res2 = a2.splice(1, 2);

console.log(a2);   // [1, 4, 5]
console.log(res2); // [2, 3]

要素を削除して追加

// toSpliced
const a1 = [1, 2, 3, 4, 5];
const res1 = a1.toSpliced(1, 2, 'a', 'b', 'c');

console.log(a1);   // [1, 2, 3, 4, 5]
console.log(res1); // [1, 'a', 'b', 'c', 4, 5]

// splice
const a2 = [1, 2, 3, 4, 5];
const res2 = a1.splice(1, 2, 'a', 'b', 'c');

console.log(a2);   // [1, 'a', 'b', 'c', 4, 5]
console.log(res2); // [2, 3]

これからは配列からの要素の削除は toSpliced() を使って見通しよく書いていけそうで嬉しいです!
配列からの削除めんどいなと思って調べなかったら気づくこと無く slicefilter で書いているところでした… ES2022, ES2023 で配列の非破壊メソッドが結構追加されているようなので、サボらずちゃんとキャッチアップしようと思ったのでした

おわり₍ᐢ. ̫.ᐢ₎


[参考]

ダンジョン飯の 九井 諒子 さん「竜の学校は山の上」の人だったのか!