目次
概要
配列の操作において、「特定の位置に値を割り込ませたい」「指定した要素だけを書き換えたい」といった高度な編集が必要になる場面があります。
splice メソッドは、引数の渡し方を変えるだけで「追加」「削除」「置換」のすべてをこなす非常に強力なツールです。本記事では、このメソッドの仕組みを理解し、動的なリスト編集機能を実装する方法を解説します。
仕様(入出力)
splice メソッド
配列の内容を変更(要素の削除・置換・追加)し、削除された要素を返します。
| 引数・戻り値 | 説明 |
第1引数: start | 変更を開始するインデックス(0始まり)。 |
第2引数: deleteCount | 古い要素を削除する数。 ・ 0 なら削除せずに追加のみ行います(挿入)。・ 1 以上ならその数だけ削除します(削除・置換)。 |
第3引数以降: items... | 配列に追加する要素(省略可)。 削除した場所にそのままねじ込まれます。 |
| 戻り値 | 削除された要素の配列 (Array)。何も削除しなかった場合は空の配列 [] が返ります。 |
基本の使い方
引数の組み合わせによって挙動が劇的に変わります。以下の3パターンを覚えておけば完璧です。
1. 挿入する(削除数 0)
第2引数を 0 にし、第3引数に追加したい値を渡します。
const colors = ['Red', 'Blue'];
// インデックス1の位置に 'Green' を挿入
colors.splice(1, 0, 'Green');
console.log(colors); // ["Red", "Green", "Blue"]
2. 削除する(追加要素なし)
第3引数を省略し、第2引数に削除したい数を指定します。
const tasks = ['Task1', 'Task2', 'Task3'];
// インデックス1から 1つ削除
const removed = tasks.splice(1, 1);
console.log(tasks); // ["Task1", "Task3"]
console.log(removed); // ["Task2"] (削除されたもの)
3. 置換する(削除して追加)
削除と追加を同時に行うことで、実質的な「置き換え」を実現します。
const members = ['Alice', 'Bob', 'Charlie'];
// インデックス1(Bob)を削除し、'Dave' と 'Eve' を追加
members.splice(1, 1, 'Dave', 'Eve');
console.log(members); // ["Alice", "Dave", "Eve", "Charlie"]
コード全文(HTML / JavaScript)
RPGゲームのパーティ編成画面をイメージしたデモです。
現在のパーティメンバーに対し、「交代(置換)」や「助っ人参入(挿入)」を行う操作を実装します。
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Party Editor</title>
<style>
body { font-family: sans-serif; padding: 20px; background-color: #f0f2f5; }
.editor-container {
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
max-width: 500px;
}
.member-list {
list-style: none;
padding: 0;
margin-bottom: 20px;
}
.member-item {
padding: 10px;
border-bottom: 1px solid #eee;
display: flex;
justify-content: space-between;
align-items: center;
}
.index-badge {
background: #ddd;
color: #555;
padding: 2px 8px;
border-radius: 12px;
font-size: 0.8em;
margin-right: 10px;
}
.controls {
display: grid;
gap: 10px;
background: #f9f9f9;
padding: 15px;
border-radius: 6px;
}
.input-group { display: flex; gap: 10px; }
input, select { padding: 8px; border: 1px solid #ccc; border-radius: 4px; }
button {
padding: 10px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-weight: bold;
}
button:hover { background-color: #45a049; }
.log-area {
margin-top: 15px;
font-size: 0.9em;
color: #d32f2f;
}
</style>
</head>
<body>
<div class="editor-container">
<h3>現在のパーティメンバー</h3>
<ul id="party-list" class="member-list">
</ul>
<div class="controls">
<label>操作対象のインデックス(場所):</label>
<div class="input-group">
<input type="number" id="target-index" value="1" min="0" style="width: 60px;">
<select id="action-type">
<option value="insert">割り込み参加 (挿入)</option>
<option value="replace">メンバー交代 (置換)</option>
<option value="remove">離脱 (削除)</option>
</select>
</div>
<input type="text" id="new-name" placeholder="新しいメンバー名">
<button id="btn-execute">実行</button>
</div>
<div id="action-log" class="log-area"></div>
</div>
<script src="party_editor.js"></script>
</body>
</html>
JavaScript
/**
* パーティ編成エディタ
* spliceメソッドを使用したリスト操作デモ
*/
// 初期のパーティメンバー
const party = ['勇者', '戦士', '魔法使い', '僧侶'];
// DOM要素
const listElement = document.getElementById('party-list');
const indexInput = document.getElementById('target-index');
const nameInput = document.getElementById('new-name');
const actionSelect = document.getElementById('action-type');
const executeButton = document.getElementById('btn-execute');
const logElement = document.getElementById('action-log');
/**
* リストを描画する関数
*/
const renderList = () => {
listElement.innerHTML = '';
party.forEach((member, index) => {
const li = document.createElement('li');
li.className = 'member-item';
li.innerHTML = `
<span><span class="index-badge">${index}</span> ${member}</span>
`;
listElement.appendChild(li);
});
// 入力欄の最大値を更新
indexInput.max = party.length;
};
/**
* 編集実行関数
*/
const executeAction = () => {
const index = parseInt(indexInput.value, 10);
const action = actionSelect.value;
const newName = nameInput.value.trim();
// バリデーション
if (isNaN(index) || index < 0 || index > party.length) {
logElement.textContent = 'エラー: 正しいインデックスを指定してください。';
return;
}
if ((action === 'insert' || action === 'replace') && !newName) {
logElement.textContent = 'エラー: メンバー名を入力してください。';
return;
}
logElement.textContent = ''; // ログクリア
let message = '';
// ★ spliceメソッドによる分岐処理
switch (action) {
case 'insert':
// 削除数0で挿入
party.splice(index, 0, newName);
message = `${index}番目に「${newName}」が割り込みました。`;
break;
case 'replace':
// 1つ削除して、新しい要素を入れる
// 戻り値(配列)の0番目を取得してログに表示
const replaced = party.splice(index, 1, newName);
message = `「${replaced[0]}」が「${newName}」に交代しました。`;
break;
case 'remove':
// 1つ削除するだけ
if (index >= party.length) {
logElement.textContent = 'エラー: 削除できるメンバーがいません。';
return;
}
const removed = party.splice(index, 1);
message = `「${removed[0]}」が離脱しました。`;
break;
}
// 画面更新
renderList();
logElement.textContent = message;
nameInput.value = ''; // 入力欄クリア
};
// 初期表示
renderList();
// イベント登録
executeButton.addEventListener('click', executeAction);
カスタムポイント
- 複数削除・複数追加:コード例では「1人の交代」ですが、
splice(index, 2, 'A', 'B')のように引数を調整すれば、「2人まとめて交代」といった機能も簡単に実装できます。 - 戻り値の活用:「置換」や「削除」の場合、
spliceは削除された要素を配列形式で返します。これを「解雇リスト」や「履歴」として別の配列に保存する機能を追加すると、より実用的になります。
注意点
- 破壊的メソッドである
spliceは元の配列を直接書き換えます。元の配列を残しておきたい場合は、先に[...party]などでコピーを作成してからspliceするか、次項のtoSplicedを検討してください。 - 戻り値は常に「配列」たとえ要素を1つしか削除しなくても、戻り値は
['削除された要素']という配列形式です。中身の値そのものを取り出すにはresult[0]とアクセスする必要があります。 - 削除カウントの省略リスク第2引数(削除数)を省略すると、開始位置から末尾までの全要素が削除されてしまいます。意図しない大量削除を防ぐため、必ず数値を指定しましょう。
応用
元の配列を変えない toSpliced (ES2023)
最新のJavaScriptでは、元の配列を変更せず、変更後の新しい配列を返す toSpliced メソッドが利用可能です。
const original = ['A', 'B', 'C'];
// インデックス1を 'X' に置換した新しい配列を作成
// original は変更されない
const newArray = original.toSpliced(1, 1, 'X');
console.log(original); // ["A", "B", "C"]
console.log(newArray); // ["A", "X", "C"]
まとめ
splice メソッドは、配列のあらゆる変更操作(CRUDのUpdate/Delete)を担う非常に重要なメソッドです。
- 追加(Insert):
splice(i, 0, val) - 削除(Delete):
splice(i, 1) - 置換(Replace):
splice(i, 1, val)
この3つの引数パターンを指に覚え込ませておけば、配列データの編集で困ることはなくなるでしょう。
