JavaScriptのプログラム開発において、配列から特定の要素を削除する操作は、最も頻繁に行われるタスクの一つです。
アプリケーションのデータ管理からUIの更新にいたるまで、適切な配列操作はパフォーマンスとコードの可読性に直結します。
かつてのJavaScriptでは、破壊的なメソッドであるspliceが主流でしたが、現代のプログラミングでは不変性(イミュータビリティ)を重視する傾向が強まっています。
本記事では、伝統的な手法から2023年以降に標準化された最新のtoSplicedまで、配列要素の削除に関するあらゆる手法を詳細に解説します。
配列の末尾や先頭から要素を削除する基本メソッド
配列の端にある要素を削除する場合、専用のメソッドを使用するのが最も効率的です。
これらのメソッドは非常に高速であり、スタックやキューといったデータ構造を扱う際によく利用されます。
popメソッドによる末尾の削除
popメソッドは、配列の最後にある要素を削除し、その要素を返します。
このメソッドは元の配列を直接変更する破壊的なメソッドです。
const fruits = ["apple", "banana", "orange"];
const lastItem = fruits.pop(); // "orange"を削除
console.log(fruits);
console.log(lastItem);
["apple", "banana"]
"orange"
shiftメソッドによる先頭の削除
shiftメソッドは、配列の最初にある要素を削除し、残りの要素のインデックスを一つずつ前にずらします。
要素数が多い配列に対してshiftを頻繁に行うと、インデックスの再計算が発生するため、パフォーマンスに影響を与える可能性があります。
const colors = ["red", "green", "blue"];
const firstItem = colors.shift(); // "red"を削除
console.log(colors);
console.log(firstItem);
["green", "blue"]
"red"
指定した位置の要素を削除する splice メソッド
配列の任意の位置にある要素を削除したい場合、古くから使われてきたのがspliceメソッドです。
このメソッドは非常に多機能ですが、元の配列を書き換えてしまう破壊的なメソッドである点に注意が必要です。
spliceの基本的な構文
第一引数に削除を開始するインデックス、第二引数に削除する個数を指定します。
第二引数を省略した場合は、指定したインデックスから末尾までのすべての要素が削除されます。
const numbers = [10, 20, 30, 40, 50];
// インデックス2から1つの要素を削除
numbers.splice(2, 1);
console.log(numbers);
[10, 20, 40, 50]
複数要素の同時削除
spliceを使用すれば、一度の呼び出しで連続した複数の要素を取り除くことも可能です。
const letters = ["a", "b", "c", "d", "e"];
// インデックス1から3つの要素を削除
letters.splice(1, 3);
console.log(letters);
["a", "e"]
最新の非破壊メソッド toSpliced
2023年のECMAScript(ES2023)で導入されたtoSplicedは、現代のJavaScript開発における重要な転換点となりました。
これまでのspliceとは異なり、元の配列を変更せず、削除操作を適用した新しい配列を返却します。
toSplicedによる安全な要素削除
ReactやVue.jsなどのモダンなフレームワークでは、状態(State)を直接変更しない「不変性」が重視されます。
toSplicedを使用することで、元のデータを保持したまま特定の要素を除外した新しいリストを生成できます。
const originalArray = ["React", "Vue", "Angular", "Svelte"];
// インデックス2から1つ削除した新しい配列を作成
const newArray = originalArray.toSpliced(2, 1);
console.log("元の配列:", originalArray);
console.log("新しい配列:", newArray);
元の配列: ["React", "Vue", "Angular", "Svelte"]
新しい配列: ["React", "Vue", "Svelte"]
ブラウザ対応と利用シーン
toSplicedは最新のブラウザ環境では広くサポートされていますが、古い環境をターゲットにする場合はポリフィルが必要です。
破壊的な副作用を避けたい大規模な開発プロジェクトにおいて、このメソッドの採用はコードの品質を高める鍵となります。
条件に一致する要素を一括削除する filter メソッド
特定のインデックスではなく、「値が◯◯であるもの」や「特定の条件を満たすもの」を削除したい場合には、filterメソッドが最適です。
filterは厳密には削除ではなく、条件に一致する要素だけで構成された新しい配列を抽出する処理を行います。
特定の値を持つ要素を除外する
例えば、数値のリストから特定の数値をすべて取り除きたい場合に非常に便利です。
const data = [1, 5, 8, 5, 10, 5, 12];
// 値が5でないものだけを残す(=5を削除する)
const filteredData = data.filter(item => item !== 5);
console.log(filteredData);
[1, 8, 10, 12]
複雑な条件による削除
オブジェクトの配列から特定のプロパティを持つ要素を除外する際にも、filterは威力を発揮します。
const users = [
{ id: 1, name: "Tanaka", active: true },
{ id: 2, name: "Sato", active: false },
{ id: 3, name: "Suzuki", active: true }
];
// activeがtrueのユーザーのみを残す
const activeUsers = users.filter(user => user.active);
console.log(activeUsers);
[{ id: 1, name: "Tanaka", active: true }, { id: 3, name: "Suzuki", active: true }]
delete 演算子の注意点と回避策
JavaScriptにはdelete演算子が存在しますが、配列の要素削除にこれを使用することは推奨されません。
なぜなら、deleteは要素の値を消去するだけで、配列のメモリ上の空き地(empty/undefined)を残してしまうからです。
delete演算子の挙動確認
以下のコードを実行すると、配列の長さ(length)が変化しないことがわかります。
const items = ["A", "B", "C"];
delete items[1];
console.log(items);
console.log(items.length);
["A", empty, "C"]
3
このように、「穴あき」の状態の配列(疎な配列)ができてしまうと、反復処理などで予期せぬ挙動を引き起こす原因となります。
そのため、要素を完全に消し去りたい場合は必ずsplice、toSpliced、またはfilterを使用しましょう。
配列のすべての要素を削除する方法
配列を空にしたい場合、状況に応じていくつかの手法を使い分ける必要があります。
変数の宣言方法や、他の参照が残っているかどうかによって最適な方法は異なります。
lengthプロパティを0にする
最も効率的かつ一般的な方法は、配列のlengthプロパティに0を代入することです。
let list = [1, 2, 3, 4, 5];
list.length = 0;
console.log(list);
[]
この手法は、同じ配列オブジェクトを別の変数で参照している場合、その参照先もすべて空になるという特徴があります。
新しい空配列を代入する
単にその変数が指す先を新しい空の配列に変える方法です。
let list = [1, 2, 3, 4, 5];
list = [];
console.log(list);
[]
ただし、この方法は変数をletで宣言している必要があり、他の変数が古い配列を参照していた場合は、その古い配列の中身は消えません。
削除手法の比較表
これまでに紹介した手法の主な特徴と使い分けを以下の表にまとめました。
| メソッド | 破壊性 | 主な用途 | 返り値 |
|---|---|---|---|
pop() | 破壊的 | 末尾の1要素を削除 | 削除された要素 |
shift() | 破壊的 | 先頭の1要素を削除 | 削除された要素 |
splice() | 破壊的 | 指定位置の複数要素を削除・置換 | 削除された要素の配列 |
toSpliced() | 非破壊的 | 指定位置を削除した新配列を作成 | 新しい配列 |
filter() | 非破壊的 | 条件に合う要素を抽出して新配列を作成 | 新しい配列 |
パフォーマンスに関する考察
大規模なデータを扱う場合、削除操作のコストも考慮する必要があります。
spliceやshiftのように、配列の中間の要素を削除する操作は、それ以降のすべての要素のインデックスを再配置するコストがかかります。
計算量で表すと、最悪の場合O(n)となります。
一方で、popのように末尾の要素を削除する操作は、インデックスの再配置が不要なためO(1)で完了し、非常に高速です。
パフォーマンスが極めて重要なケースでは、要素を詰め直すのではなく、削除フラグを立てるなどの別のアプローチも検討されるべきです。
実戦での使い分けガイドライン
どの手法を使うべきか迷った際は、以下のガイドラインを参考にしてください。
まず、基本的には非破壊的な手法(filter, toSpliced)を優先して検討しましょう。
不変性を保つことで、デバッグが容易になり、予期せぬバグの発生を防ぐことができます。
一方で、ループ内で大量の配列操作を行う際、メモリの再割り当てを避けてパフォーマンスを最大化したい場合には、破壊的なspliceが適しています。
特に、非常に巨大な配列を操作しており、新しい配列を作成するためのメモリ消費を抑えたい場面ではspliceが有効です。
インデックスがわかっている場合
単一のインデックスを指定して削除し、元の配列を維持したいならtoSplicedが最も簡潔です。
もしプロジェクトが古いブラウザに対応する必要があり、toSplicedが使えないなら、sliceを組み合わせて同様の処理を記述できます。
const index = 2;
const items = ["A", "B", "C", "D"];
const newItems = [...items.slice(0, index), ...items.slice(index + 1)];
console.log(newItems);
["A", "B", "D"]
値に基づいて削除したい場合
重複する値を一括で削除したいのか、最初に見つかった一つだけを削除したいのかで手法が変わります。
一括削除であればfilterの一択です。
最初の一つだけを削除したい場合は、indexOfでインデックスを見つけてからspliceやtoSplicedを適用するのがスマートです。
まとめ
JavaScriptにおける配列の削除手法は、言語の進化とともに多様化してきました。
古典的なpop、shift、spliceは強力ですが、元のデータを直接書き換える副作用に注意が必要です。
最新のtoSplicedや汎用性の高いfilterを使いこなすことで、より安全で保守性の高いコードを記述できるようになります。
用途に応じて、破壊的か非破壊的か、またはインデックスベースか条件ベースかを整理して選択することが重要です。
本記事で紹介した各メソッドの特性を理解し、2026年現在のモダンなJavaScript開発に役立ててください。
