【JavaScript】配列操作の万能ナイフ!spliceメソッドで追加・削除・置換を自在に操る

目次

概要

配列の操作において、「特定の位置に値を割り込ませたい」「指定した要素だけを書き換えたい」といった高度な編集が必要になる場面があります。

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 は削除された要素を配列形式で返します。これを「解雇リスト」や「履歴」として別の配列に保存する機能を追加すると、より実用的になります。

注意点

  1. 破壊的メソッドであるsplice元の配列を直接書き換えます。元の配列を残しておきたい場合は、先に [...party] などでコピーを作成してから splice するか、次項の toSpliced を検討してください。
  2. 戻り値は常に「配列」たとえ要素を1つしか削除しなくても、戻り値は ['削除された要素'] という配列形式です。中身の値そのものを取り出すには result[0] とアクセスする必要があります。
  3. 削除カウントの省略リスク第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つの引数パターンを指に覚え込ませておけば、配列データの編集で困ることはなくなるでしょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次