DOMの要素の削除(removeChild / remove

DOMからノード(要素やテキストなど)を取り除く代表的な方法は次の2つです。

  • parent.removeChild(child)(古くからある標準的手法)

  • node.remove()ChildNodeに追加された簡潔な手法)


基本

1) parent.removeChild(child)

  • 使い方:親ノードから、指定した子ノードを取り除きます。

  • 返り値:取り除かれたノード(再利用可)。

  • 例外childparentの子でない場合は NotFoundError を投げます。

html
<ul id="list"> <li>Apple</li> <li id="to-remove">Banana</li> <li>Cherry</li> </ul> <script> const parent = document.getElementById('list'); const child = document.getElementById('to-remove'); const removed = parent.removeChild(child); // removed は <li id="to-remove">…</li> // 必要なら再挿入できる parent.appendChild(removed); </script>

2) node.remove()

  • 使い方:そのノード自身が属する親から自分を取り除きます(親取得不要)。

  • 返り値:なし。

  • 例外:親がなければ何もしません(例外を投げない)。

html
<div id="ad">広告</div> <script> document.getElementById('ad').remove(); // 親があれば削除、なければ何もしない </script>

違いの整理

  • 記述量remove()は短く書けます。removeChildは親と子の2つの参照が必要。

  • エラーハンドリングremoveChildは親子関係でなければ例外remove()黙って無視

  • 返り値removeChildは削除ノードを返す(後で再利用可)。remove()は返さない。

  • 対応範囲:どちらもモダンブラウザで使用可。古い環境互換が必要ならremoveChildかポリフィルを使う。


代表的なパターン

コンテナ内の子要素をすべて削除

いずれも「子ノード全消去」ですが、特性が少しずつ異なります。

js
// 1) 安全で確実(ライブコレクションでも乱れにくい) while (container.firstChild) { container.removeChild(container.firstChild); } // 2) モダン・簡潔(Node.replaceChildren) container.replaceChildren(); // 全子ノードを一括で置換(引数なしで空に) // 3) 速いことが多いが副作用に留意(イベント等は当然消える) container.textContent = ''; // テキスト・子を空に(HTMLも除去) container.innerHTML = ''; // 同上(パースコストあり、script再実行などの注意)

メモ:getElementsBy*で得られる HTMLCollection(ライブ) を反復しながら削除すると走査が崩れがちです。
while (firstChild) 方式か、Array.from(collection).forEach(...) のように静的配列へコピーしてから削除すると安全です。
querySelectorAllNodeList(静的) はそのまま反復削除しても崩れにくいです。

指定の複数要素を一括削除

js
document.querySelectorAll('.temp').forEach(el => el.remove());

別の親へ移動(暗黙の削除)

同じノードを他の親に append/appendChild すると、元の親からは自動的に取り除かれます

js
newParent.appendChild(oldChild); // oldParent からは自動で削除される

イベントリスナー・メモリの注意点

  • ノードを削除すると、そのノードに紐づいたイベントリスナーは実質使われなくなります。通常はガベージコレクタが回収しますが、外部から参照が残っていると回収されません(変数に保持している、Mapに入れたまま等)。不要になった参照は適切に破棄してください。

  • 多数の動的要素でリスナー管理が煩雑な場合は、イベント委譲(親に一つ付けてevent.targetで分岐)を検討すると削除時の管理が楽です。

  • 進行中のイベント中に自身を削除しても、そのイベントのバブリングは基本的に継続します。中断したい場合は event.stopPropagation() を用います。


レイアウト・アニメーション連携

削除前にフェードアウトするなどの演出は、CSSトランジションとtransitionendで行い、完了後に削除します。

js
const el = document.querySelector('.toast'); el.classList.add('fade-out'); el.addEventListener('transitionend', () => el.remove(), { once: true });

例外/エラー対策

  • removeChild は親子関係でないと NotFoundError。実行前に parent.contains(child)child.parentNode === parent を確認すると安全。

  • null 参照防止:document.getElementById('x')?.remove() のようにオプショナルチェーンを活用。


remove() の簡易ポリフィル(古い環境向け)

js
(function(proto) { if (!proto.remove) { proto.remove = function() { if (this.parentNode) this.parentNode.removeChild(this); }; } })(Element.prototype);

必要に応じて CharacterData.prototypeDocumentType.prototype にも同様に付与します。


アクセシビリティの注意

フォーカス中の要素を削除するとフォーカスが失われることがあります。次にフォーカスすべき要素(例:近傍のボタンやコンテナ)に明示的に focus() を移すと操作感が向上します。

js
const next = button.nextElementSibling || button.parentElement; button.remove(); next?.focus();

まとめ

  • 単体削除で簡潔に:node.remove()

  • 削除ノードを再利用したい/厳密に:parent.removeChild(child)(返り値あり・不一致は例外)

  • 多数削除:while (firstChild) / replaceChildren() / 静的リスト化してループ

  • メモリ/イベント:参照を残さない、委譲で管理簡素化、必要ならバブリング制御

  • UX:アニメーション後に削除、フォーカス移動も考慮

ChatGPT5 生成日:2025/09/11