0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

配列から要素を削除する時、delete/splice/filterはどう違うか

0
Posted at

JavaScriptで配列から特定の要素を取り除きたいとき、delete・splice・filterのどれを使っても「一見消えたように見える」ため、違いを意識せずに使ってしまうことがあります。しかし挙動はそれぞれまったく違い、選び方を誤ると画面に「穴」が残るバグを生みます。実際にNode.jsで実行して挙動を比較しました。

Before: deleteで「消したつもり」が事故になる

let arr = [1, 2, 3, 4, 5];
delete arr[2];

console.log(arr);
// [ 1, 2, <1 empty item>, 4, 5 ]

console.log(arr.length);
// 5 ← 減っていない!

console.log(2 in arr);
// false ← インデックス2はもう存在しない

console.log(JSON.stringify(arr));
// [1,2,null,4,5] ← JSONにするとnullになる

delete演算子は、配列の要素を「削除」するのではなく、そのインデックスの中身を空にするだけです。配列の長さ(length)は変わらず、該当インデックスは「値がない穴(empty item)」として残ります。

この「穴」は厄介で、たとえばmap()で処理すると、穴の部分はコールバック関数自体がスキップされます。

console.log(arr.map(x => x * 2));
// [ 2, 4, <1 empty item>, 8, 10 ] ← 3番目だけ2倍にならず穴のまま

画面に配列を描画するコードだと、「なぜか3番目だけ表示が壊れる/空白になる」という形でバグが表面化します。しかもlengthが5のままなので、arr.lengthを使った件数表示にも影響が出ます。

After①: spliceは「その場で」正しく削除する

let arr2 = [1, 2, 3, 4, 5];
let removed = arr2.splice(2, 1); // インデックス2から1個削除

console.log(arr2);
// [ 1, 2, 4, 5 ] ← ちゃんと詰まって4要素に

console.log(arr2.length);
// 4 ← 正しく減っている

console.log(removed);
// [ 3 ] ← 削除された要素が戻り値で返ってくる

splice(開始位置, 削除する個数)は、指定した範囲の要素を実際に取り除き、後ろの要素を前に詰めてくれます。lengthも正しく更新されるため、deleteのような「穴」は残りません。削除した要素が戻り値で返ってくるのも地味に便利です(「削除する前に確認したい」場面で使えます)。

ただしspliceは元の配列そのものを直接書き換える破壊的メソッドなので、Reactのstateのように「元のデータを直接変更してはいけない」場面では注意が必要です(以前扱ったsort()の破壊的挙動は「並べ替えで元配列の順序が変わる」話でしたが、今回は「要素の削除で配列の形そのものが変わる」話なので、注意すべきポイントは別物です)。

After②: filterは「壊さず」新しい配列を作る

let arr3 = [1, 2, 3, 4, 5];
let filtered = arr3.filter(x => x !== 3);

console.log(filtered);
// [ 1, 2, 4, 5 ]

console.log(arr3);
// [ 1, 2, 3, 4, 5 ] ← 元の配列は変わっていない

filterは「条件に合う要素だけを集めた新しい配列」を作って返します。元の配列(arr3)はそのまま残るため、Reactのstate更新(setItems(items.filter(...))のような書き方)と相性が良い方法です。

使い分けの結論

方法 元の配列 lengthの更新 向いている場面
delete 変更される(穴が残る) されない 基本的には避ける
splice 変更される(詰まる) される 配列を直接書き換えてよい場面、削除した要素も使いたい場面
filter 変更されない 新配列で正しい Reactのstate更新など、元データを壊したくない場面

「配列から要素を消したい」と思ったときにAIへ丸投げすると、deleteを提案されることがあります。動いているように見えてもlengthやmap()の挙動でハマる可能性があるため、出てきたコードがdeleteを使っていたら、spliceかfilterへの置き換えを検討してみてください。


未経験者向けの講座を運営しています

未経験から Next.js + Supabase + Claude Code で Webアプリを公開するまで を、全24セッションで体系化した教材です。Claude Code を学習パートナーにする CLAUDE.md と学習モード(learner / developer)の設計までセットで含みます。

※ Qiita 読者の方には易しすぎる内容なので、初心者の知り合いへの紹介や社内研修の参考としてどうぞ。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?