この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:5
ページ更新者:guest
更新日時:2026-06-11 07:07:02

タイトル: 子要素の削除
SEOタイトル: JavaScript / jQuery で子要素を全削除する方法(empty / replaceChildren / innerHTML 比較)

この記事の要点
  • jQuery: $(el).empty()(子要素のみ削除) vs $(el).remove()(自身も削除)
  • Vanilla 最新: el.replaceChildren()(2020〜、最も推奨)
  • Vanilla 古典: el.innerHTML = ""(簡単だがイベントリスナーが残るブラウザあり)
  • 性能重視: while (el.firstChild) el.removeChild(el.firstChild) ループ
  • メモリリーク防止: 子要素にイベントリスナー / addEventListener を付けていたら明示削除推奨

子要素を削除する 5 つの方法

「リストをクリアして再描画」「モーダルの中身をリセット」など、子要素を全削除するシーンは頻出します。JavaScript には複数のやり方があり、性能・安全性・古い API か新しい API かで選択が変わります。

方法対応速度イベント残し備考
el.replaceChildren()2020〜★ 速いクリア現代の推奨
el.innerHTML = ''古くから速いクリアされない場合ありシンプル、最頻出
while + removeChild古くから速いクリア確実
$(el).empty()jQuery普通★ 自動クリアjQuery 利用時
$(el).remove()jQuery普通クリア自身も消える

方法1: replaceChildren()(モダン推奨)

// 子要素を全削除
const list = document.getElementById('list');
list.replaceChildren();

// 削除と差し替えを同時に
list.replaceChildren(
  Object.assign(document.createElement('li'), { textContent: 'New 1' }),
  Object.assign(document.createElement('li'), { textContent: 'New 2' }),
);

// 配列展開もできる
const items = ['A', 'B', 'C'].map(t => {
  const li = document.createElement('li');
  li.textContent = t;
  return li;
});
list.replaceChildren(...items);

Chrome 86 / Safari 14 / Firefox 78(2020 年〜)で利用可能。IE はサポートしませんが、現代では考慮不要です。

方法2: innerHTML = '' (最頻出)

const list = document.getElementById('list');
list.innerHTML = '';

// 注意: innerHTML はパースが入るので、信頼できない値を代入するのは XSS リスク
// 空文字なら問題なし

シンプルで分かりやすい反面、古いブラウザではイベントリスナーや関連オブジェクトの解放が不完全で、メモリリークの温床になることがありました。モダンブラウザでは概ね問題ないですが、後述の replaceChildren() を使うのが安全。

方法3: while + removeChild(古典)

const list = document.getElementById('list');

while (list.firstChild) {
  list.removeChild(list.firstChild);
}

// あるいは lastChild から
while (list.lastChild) {
  list.removeChild(list.lastChild);
}

すべてのブラウザで確実に動作します。性能も高く、長くベストプラクティスとされていました。今では replaceChildren() に置き換わっていますが、IE / 古い WebView を相手にするときは依然有効。

方法4: jQuery .empty() / .remove()

// 子要素のみ全削除(自身は残る)
$('#list').empty();

// 自身も含めて削除
$('#list').remove();

// .detach() は DOM から外すがデータ・イベントは保持(再 append 可能)
const $kept = $('#list').detach();
$('body').append($kept);

// 子要素だけ削除して新しい要素を入れる
$('#list').empty().append('
  • New 1
  • New 2
  • ');

    .empty() は jQuery が子孫の data / event を自動的に解放するためメモリリーク対策として優秀でした。Vanilla の場合は手動で removeEventListener しないと残るケースに注意。

    性能比較(概念)

    1 万要素削除のおおまかな速度感所要時間
    replaceChildren()★ 最速クラス
    innerHTML = ''速い(パース不要のため)
    while + removeChild速い
    1 つずつ removeChild(forEach)やや遅い(再描画フラッシュが入ることあり)
    jQuery .empty()★ 一段遅い(イベント解放処理あり)

    体感差は小規模(数百要素)では誤差ですが、数千〜数万になると replaceChildren() の優位が見えます。

    メモリリーク防止のコツ

    削除する前にイベントリスナーを明示的に外すと、循環参照によるリークを防げます:

    // ❌ 削除しても closure 経由でリスナーが残るパターン
    const btn = document.createElement('button');
    btn.addEventListener('click', () => bigState.doSomething());
    list.appendChild(btn);
    // 後で list.innerHTML = '' しても、登録した {bigState} の参照が残る可能性
    
    // ✅ 削除前にリスナーを外す
    const handler = () => bigState.doSomething();
    btn.addEventListener('click', handler);
    btn._handler = handler;
    // ...
    btn.removeEventListener('click', btn._handler);
    list.removeChild(btn);
    
    // ✅ AbortController で一括解除
    const ctrl = new AbortController();
    btn.addEventListener('click', handler, { signal: ctrl.signal });
    // 後で
    ctrl.abort();    // 全リスナー解除
    list.replaceChildren();

    React / Vue / Svelte の場合

    仮想 DOM / リアクティブ系のフレームワークは、状態を空配列にするだけで DOM の子要素削除を内部処理してくれます。直接 DOM を触る必要はありません。

    // React
    const [items, setItems] = useState([1, 2, 3]);
    setItems([]);   // → 自動で子要素削除
    
    // Vue
    const items = ref([1, 2, 3]);
    items.value = [];
    
    // Svelte
    let items = [1, 2, 3];
    items = [];

    テンプレートのリセット(よくある実装例)

    function renderList(data) {
      const list = document.getElementById('list');
    
      // クリア
      list.replaceChildren();
    
      // テンプレート要素を複製して append
      const tpl = document.getElementById('item-tpl');
      for (const d of data) {
        const node = tpl.content.cloneNode(true);
        node.querySelector('.name').textContent = d.name;
        node.querySelector('.price').textContent = '¥' + d.price.toLocaleString();
        list.appendChild(node);
      }
    }
    
    renderList([{ name: 'Apple', price: 120 }, { name: 'Banana', price: 80 }]);

    FAQ

    Q: innerHTML = '' は遅い?
    A: 空文字代入は HTML パース不要で十分高速です。「大量 HTML 文字列を innerHTML に代入」は遅い、というよく聞く話と混同しないこと。

    Q: 削除した子要素を再利用したい
    A: el.removeChild(child) で取り出した child をそのまま別の親に appendChild() できます。jQuery なら .detach()

    Q: replaceChildren が古いブラウザで動かない
    A: モダンブラウザのみ対応。IE 11 等を相手にする場合は while (el.firstChild) 方式にフォールバック。