DOM 操作
DOM(Document Object Model)は、ブラウザが HTML ドキュメントから作成するツリーです。JavaScript でこのツリーを操作することで、ページのコンテンツ、構造、属性を動的に変更できます。木から果物を摘み取ったり、新しい枝を接ぎ木したり、枯れ木を切り落としたりするようなものです。
要素の選択
DOM 操作の第一歩は常に「まず見つけること」です。
| メソッド | 返り値 | 説明 |
|---|---|---|
getElementById('id') |
単一要素 | 最速。id は一意 |
getElementsByClassName('cls') |
HTMLCollection | ライブコレクション。DOM の変更と同期 |
getElementsByTagName('tag') |
HTMLCollection | 上記と同じ |
querySelector('selector') |
単一要素 | CSS セレクタ。最初のマッチを返す |
querySelectorAll('selector') |
NodeList | 静的コレクション。DOM の変更に影響されない |
💡
querySelector ファミリ vs getElementBy*:前者は CSS セレクタを使用(より柔軟)、後者はわずかにパフォーマンスが良い。日常開発では querySelector を推奨。より直感的です。
例:5つの選択メソッドの比較
HTML
<div id="box" class="card active">こんにちは</div>
<div class="card">世界</div>
<p class="card">JS</p>
<script>
const byId = document.getElementById('box');
console.log('byId:', byId.textContent);
const byClass = document.getElementsByClassName('card');
console.log('byClass 数:', byClass.length);
const byTag = document.getElementsByTagName('p');
console.log('byTag:', byTag[0].textContent);
const first = document.querySelector('.card');
console.log('querySelector:', first.textContent);
const all = document.querySelectorAll('.card');
console.log('querySelectorAll 数:', all.length);
</script>
コンテンツの変更
要素を見つけた後、最も一般的なニーズは「何と言っているか」を変更することです。
textContent:プレーンテキストの読み書き。安全で効率的。innerHTML:HTML 文字列の読み書き。タグを挿入できるが、XSS リスクがある。
⚠️ ユーザーが提供したコンテンツを挿入する際に
innerHTML を絶対に使わないでささい。攻撃者が悪意のあるスクリプトを注入できます。見知らぬ人の手紙を掲示板にそのまま貼り付けるようなもので、手紙に「爆弾」が含まれているかもしれません。
例:textContent と innerHTML の比較
HTML
<div id="safe"></div>
<div id="danger"></div>
<script>
const safe = document.getElementById('safe');
safe.textContent = '<b>これは太字にはなりません</b>';
const danger = document.getElementById('danger');
danger.innerHTML = '<b>これは太字になります</b>';
</script>
属性の変更
HTML 要素の属性(id、class、src、href など)も JS で読み書きできます。
| メソッド | 説明 |
|---|---|
getAttribute('name') |
属性値の読み取り |
setAttribute('name', 'value') |
属性の設定 |
removeAttribute('name') |
属性の削除 |
💡 一部の属性はドット記法で直接アクセスできます:
el.id、el.className、el.src。ただし、カスタム属性(data-*)には getAttribute または el.dataset を使いましょう。
例:リンク属性の操作
HTML
<a id="link" href="https://example.com" target="_blank">サンプルリンク</a>
<script>
const link = document.getElementById('link');
console.log('href:', link.getAttribute('href'));
link.setAttribute('href', 'https://mdn.io');
link.setAttribute('title', 'クリックで MDN へ移動');
link.removeAttribute('target');
console.log('変更後:', link.getAttribute('href'));
</script>
要素の作成と挿入
DOM 操作のコア能力の1つ:要素を「無から作成」し、ツリーに取り付けること。
| メソッド | 説明 |
|---|---|
createElement('tag') |
要素ノードの作成 |
createTextNode('text') |
テキストノードの作成 |
appendChild(child) |
末尾に追加 |
insertBefore(new, ref) |
ref の前に挿入 |
例:リスト項目の動的追加
HTML
<ul id="list">
<li>既存のアイテム</li>
</ul>
<script>
const list = document.getElementById('list');
const li = document.createElement('li');
li.textContent = '新しく追加されたアイテム';
list.appendChild(li);
const li2 = document.createElement('li');
li2.textContent = '先頭に挿入';
list.insertBefore(li2, list.firstChild);
</script>
要素の削除と複製
| メソッド | 説明 |
|---|---|
removeChild(child) |
親が子ノードを削除 |
remove() |
要素が自身を削除(新しい API) |
cloneNode(true/false) |
true = ディープクローン(子要素含む)、false = シャロークローン |
💡
remove() は removeChild() よりシンプルですが、削除されたノードをさらに処理する必要がある場合は removeChild() を使いましょう。削除されたノードを返します。
例:削除と複製
HTML
<ul id="fruits">
<li>りんご</li>
<li>バナナ</li>
<li>オレンジ</li>
</ul>
<script>
const fruits = document.getElementById('fruits');
const banana = fruits.children[1];
const removed = fruits.removeChild(banana);
console.log('削除:', removed.textContent);
const clone = fruits.cloneNode(true);
document.body.appendChild(clone);
console.log('リストを複製しました');
</script>
📖 まとめ
- 要素選択には2つの陣営:
getElementBy*(パフォーマンスが良い)とquerySelector*(より柔軟)。日常使いではquerySelectorで十分。 - テキストの変更には
textContentを使い、HTML が必要な場合のみinnerHTMLを使う。後者は XSS 対策が必要。 - 属性操作:
getAttributeで読み取り、setAttributeで書き込み、removeAttributeで削除。 - 要素作成の標準フロー:
createElement→ コンテンツ/属性の設定 →appendChildでマウント。 - 要素削除の2つの方法:
remove()(要素が自身を削除)、removeChild()(親が削除し、ノードを取得できる)。 cloneNode(true)はすべての子孫を含むディープクローン、cloneNode(false)は殻だけを複製。
❓ よくある質問
Q
querySelector が null を返した場合、どうなりますか?A
null に対してプロパティやメソッドを呼び出すと TypeError がスローされます。そのため、操作前にチェックするのが最善です:const el = document.querySelector('.xxx'); if (el) { ... }。Q
HTMLCollection と NodeList の違いは何ですか?A
HTMLCollection はライブです。DOM の変更に自動的に更新されます。querySelectorAll からの NodeList は静的スナップショットです。要素を追加/削除しながら反復処理する場合、静的コレクションの方が安全です。さもなければ無限ループになる可能性があります。Q すでに存在するノードを
appendChild するとどうなりますか?A ノードは元の位置から新しい位置に「移動」します。DOM では同じノードは1回しか出現できません。これはコピーではなく移動です。
📝 演習
- 基礎:
createElementとappendChildを使って、5つの都市名を含むリストを動的に生成するページを作成してください。 - 中級:前の演習のリストに削除ボタンを追加してください。クリック時に
removeChildを使って対応するリスト項目を削除してください。 - チャレンジ:シンプルな「メモマネージャー」を実装してください。入力フィールド + 追加ボタン。メモを追加するたびに、削除ボタン付きのカードを作成してください。削除ボタンをクリックするとそのカードが削除されます。



