DOM

DOMとは

DOM(Document Object Model)は、ブラウザが読み込んだ [[HTML]] を木構造のオブジェクトの集まりとして表現したものです。[[JavaScript]] からこの木をたどって要素を取得・変更・追加・削除することで、ページの表示を動的に書き換えられます。

HTML が「文書を書くための文字列」だとすれば、DOM は「その文書をプログラムから操作するためのオブジェクト」です。配信された HTML は確定した文字列にすぎず、読み込みの後は組み上がった木の方が画面の正本になります。開発者ツールの Elements パネルに出ているのも、HTML ファイルそのものではなくブラウザが構築した DOM です。ページ上のあらゆる変化は突き詰めればこの木への操作であり、フロントエンドの技術の多くは「DOM をどう安全に・速く・楽に書き換えるか」への答えとして生まれています。

木構造のイメージ

<body>
  <h1>タイトル</h1>
  <ul>
    <li>項目1</li>
    <li>項目2</li>
  </ul>
</body>

この HTML からは、body を親として h1ul がぶら下がり、ul の下に li が並ぶツリー構造(木)が作られます。木を構成する部品はまとめてノードと呼ばれ、親子・兄弟の関係でつながります。タグに当たるものが要素ノード、その中の文字は独立したテキストノードです。木全体の入口が document で、操作はここを起点にたどります。

JavaScriptからの操作

// 取得
const title = document.querySelector('h1');
// 変更
title.textContent = 'こんにちは';
// 追加
const item = document.createElement('li');
item.textContent = '項目3';
document.querySelector('ul').appendChild(item);
// イベント
title.addEventListener('click', () => alert('クリック!'));
操作代表的なAPI
要素の取得querySelector / getElementById
内容の変更textContent / setAttribute
追加・削除createElement / appendChild / remove
イベント登録addEventListener

イベントとDOM

クリックやキー入力は発生した要素から祖先へ順に伝わります(バブリング)。行ごとにではなく親要素へまとめてリスナーを登録するイベント委譲は、この性質を使った定石です。高頻度イベントの間引き方は [[デバウンスとスロットル]] へ。

DOMから派生する木

DOM の周辺には「DOM から作られる木」や「DOM に似た木」が並び、名前が紛らわしい部分です。

  • レンダーツリー — DOM に CSS を合成した、実際に描画される木。レイアウトとペイントはここから始まります([[ブラウザレンダリングの仕組み]])
  • アクセシビリティツリー — DOM から役割と名前を抽出した、スクリーンリーダーが読む木([[Webアクセシビリティ]])
  • Shadow DOM — 部品の内部を外から隔離した小さな木([[Web Components]])
  • 仮想DOM — フレームワークがメモリ上に持つ軽量な木。コストの高い実 DOM 操作を最小限に抑えるため、差分だけを反映します([[React]] / [[Vue.js]])
  • SVG — 図形1つ1つが DOM 要素として存在する画像形式([[SVGとCanvas]])

初学者向けポイント

  • DOM の変更は再描画のコストが高い処理です。大量の要素を1個ずつ追加するより、まとめて追加する方が速くなります
  • 文字を入れるときは innerHTML ではなく textContent を使います。innerHTML は渡した文字列をタグとして解釈するため、利用者の入力を通すと [[XSS(クロスサイトスクリプティング)]] の入口になります
  • まずは素の JavaScript で DOM 操作を体験しておくと、フレームワークが「何を代行してくれているか」が理解しやすくなります

関連技術とのつながり

  • [[HTML]] — DOM の元になる文書。解析して DOM ツリーが作られる
  • [[JavaScript]] — DOM を操作するための言語
  • [[ブラウザレンダリングの仕組み]] — DOM の構築はレンダリングの最初のステップ
  • [[SVGとCanvas]] — SVG の図形は DOM の一部として操作できる
  • [[Web Components]] — 独自タグを定義して DOM を拡張する仕組み
  • [[React]] — 手作業の DOM 操作を宣言的な記述に置き換える
  • [[SPAとMPA]] — 画面遷移そのものを DOM の書き換えで実現する
Q: DOMとは何を表したもの?
- [x] HTMLを木構造のオブジェクトとして表現したもの
- [ ] CSSのスタイル定義をまとめた設定ファイル
- [ ] サーバー側でHTMLを生成するテンプレート
解説: DOMはブラウザがHTMLを解析して作る木構造のオブジェクトで、JavaScriptから操作できます。

Q: DOMで要素を取得するAPIとして本文で挙げられているのはどれ?
- [ ] fetch
- [x] querySelector
- [ ] JSON.parse
解説: querySelector や getElementById が要素取得の代表的なAPIです。

Q: ReactやVue.jsが仮想DOMを使う目的はどれ?
- [ ] HTMLファイルの文字数を減らすため
- [ ] サーバーの通信量を減らすため
- [x] コストの高い実DOM操作を最小限に抑えるため
解説: DOMの変更は再描画コストが高いため、仮想DOMで差分だけを実DOMに反映して負荷を抑えます。

Q: イベントが発生した要素から祖先へ順に伝わる性質の名前はどれ?
- [ ] コンポジット
- [x] バブリング
- [ ] エスケープ
解説: バブリングを利用し、増減する子要素の代わりに親要素へまとめてリスナーを登録する手法をイベント委譲と呼びます。