要素の取得方法

DOMの操作(読み取り)— 要素の取得方法

DOMから要素を取得する代表的なAPIは次の4系統です。目的(唯一の要素を欲しいのか、複数か、表現力か、速度か)と返り値の型(単一要素/コレクション)コレクションがライブか静的かを押さえると使い分けが明確になります。


共通のポイント(前提)

  • どのメソッドも document だけでなく 任意の要素を起点に呼び出せます(探索範囲をその要素の子孫に限定できる)。

    • 例: sectionEl.querySelectorAll('a')

  • ライブ(動的)コレクションは DOM 変更を自動反映、静的コレクションは取得時点のスナップショットです。

  • 反復時は for...offorEach、配列化(Array.from()、スプレッド)を使うと扱いやすいです。


1) getElementById(id)

  • 用途: 一意のIDを持つ要素を1つ取得。

  • 返り値: Element | null

  • 探索対象: ドキュメント全体(※要素からは呼べません。常に document.getElementById

  • 特徴:

    • 最速クラス(ブラウザが内部に索引を持つため)。

    • 同じIDが複数あると最初の1つだけ返り、HTMLの仕様上はIDは一意が前提。

  • :

    html
    <div id="profile"></div> <script> const box = document.getElementById('profile'); if (box) { box.textContent = 'Hello'; } </script>

2) getElementsByClassName(classNames)

  • 用途: クラス名で複数一致を取得。

  • 引数: 文字列(スペース区切りで AND 条件)。"btn primary" は両方のクラスを持つ要素のみ一致。

  • 返り値: HTMLCollectionライブ

  • 探索対象: 呼び出し元の要素配下(document または任意要素)

  • 注意:

    • ライブなので、取得後にDOMを追加・削除すると自動で内容が変わる。反復中の変更で取りこぼしが起きやすい。

    • 反復や安全な操作をしたいときは 配列にコピーする。

  • :

    html
    <ul id="menu"> <li class="item active">A</li> <li class="item">B</li> </ul> <script> const menu = document.getElementById('menu'); const items = menu.getElementsByClassName('item'); // HTMLCollection (ライブ) // 安全に処理したい場合 [...items].forEach(li => li.classList.add('seen')); </script>

3) getElementsByTagName(tagName)

  • 用途: タグ名で複数一致を取得(例: "li", "p")。"*" で全要素。

  • 返り値: HTMLCollectionライブ

  • 探索対象: 呼び出し元の要素配下

  • 注意:

    • HTML文書ではタグ名の大小は区別されません(XMLでは区別される)。

    • 大量要素を一気に取る用途に向くが、ライブである点は要注意。

  • :

    js
    const rows = document.getElementsByTagName('tr'); // ライブ for (const tr of rows) { // 何らかの処理 }

4) querySelector(selector) / querySelectorAll(selector)

  • 用途: CSSセレクタで柔軟に検索。

    • querySelector最初に一致した1要素

    • querySelectorAll全一致静的 NodeList

  • 返り値:

    • querySelector: Element | null

    • querySelectorAll: NodeList静的forEach 可)

  • 探索対象: 呼び出し元の要素配下

  • セレクタ例:

    • '#app .item.active'(ID → クラス → 状態)

    • 'a[href^="/docs/"]'(前方一致)

    • ':scope > li:nth-child(2)':scope は呼び出し元要素を基点に明示)

  • 注意:

    • 静的なので、DOM変更後は再度呼び直す必要がある。

    • 表現力が高く読みやすいが、単純取得では getElementById の方が速く意図も明確。

  • :

    html
    <nav id="nav"> <a class="item active" href="/home">Home</a> <a class="item" href="/docs/start">Docs</a> </nav> <script> const nav = document.getElementById('nav'); const firstActive = nav.querySelector('.item.active'); // 1件 const docLinks = nav.querySelectorAll('a[href^="/docs/"]'); // NodeList (静的) docLinks.forEach(a => a.classList.add('doc')); </script>

ライブ vs 静的 の落とし穴と対処

  • 落とし穴: ライブな HTMLCollection を前から削除しながら反復すると、インデックスが詰まって要素をスキップする場合がある。

  • 対処:

    1. 配列にコピーしてから処理:Array.from(collection).forEach(...)

    2. 末尾から逆順で処理:for (let i = collection.length - 1; i >= 0; i--) { ... }

    3. そもそも静的な querySelectorAll を使う。


スコープの設定(document か要素か)

  • 大きなページ全体から取るより、起点要素を絞ってから検索すると可読性・性能が上がります。

    js
    // 悪い例(全体から常に検索) const titles = document.querySelectorAll('#article .title'); // 良い例(まずセクションを特定→内部だけ探索) const article = document.getElementById('article'); const titles = article.querySelectorAll('.title');

どれを選ぶべきか(指針)

  • 一意の要素が欲しい → getElementById(最速・意図が明確)

  • 多数の同種要素でクラスやタグが決まっている → getElementsByClassName / getElementsByTagName(ただしライブに注意)

  • 柔軟な条件や複合条件が必要 → querySelector / querySelectorAll(静的で安全、CSSセレクタで表現力)


まとめ表

メソッド 目的 返り値 コレクション性 ライブ/静的 スコープ
getElementById 一意IDで1件取得 `Element null` 単一
getElementsByClassName クラス一致(AND可) HTMLCollection 複数 ライブ document/要素
getElementsByTagName タグ一致("*"可) HTMLCollection 複数 ライブ document/要素
querySelector CSSで最初の一致 `Element null` 単一
querySelectorAll CSSで全一致 NodeList 複数 静的 document/要素

小さな実践例(4種を一度に体験)

html
<section id="articles"> <article class="post featured"><h2 class="title">A</h2></article> <article class="post"><h2 class="title">B</h2></article> <article class="post"><h2 class="title">C</h2></article> </section> <script> // 1) getElementById const box = document.getElementById('articles'); // 2) getElementsByClassName(ライブ) const postsLive = box.getElementsByClassName('post'); // HTMLCollection console.log(postsLive.length); // 3 // 3) getElementsByTagName(ライブ) const titlesLive = box.getElementsByTagName('h2'); // HTMLCollection // 4) querySelector / querySelectorAll(静的) const featured = box.querySelector('.post.featured'); // 最初の1件 const allTitles = box.querySelectorAll('.post .title'); // NodeList(静的) // 反復の例 allTitles.forEach(h => h.dataset.scanned = 'true'); // ライブ性の確認(要素を追加) const newPost = document.createElement('article'); newPost.className = 'post'; newPost.innerHTML = '<h2 class="title">D</h2>'; box.appendChild(newPost); console.log(postsLive.length); // 4(自動で増える) console.log(allTitles.length); // 3(静的なので増えない) </script>

補足の注意点

  • getElementsByClassName("a b")a と b の両方を持つ要素のみ一致します。順序は不問。

  • querySelectorAllNodeListforEach を持ちますが、map など配列メソッドはないため必要に応じて配列化します。

  • 大規模な探索は 起点を絞るか、セレクタを具体的にして過剰マッチを避けると効率的です。

  • HTMLではIDは一意であるべきです。重複IDは選択結果やアクセシビリティの問題を招きます。

この4系統を「一意か複数か」「表現力」「ライブか静的か」で選び分けると、意図どおりで安全・効率的な DOM 取得ができます。

ChatGPT5 生成日:2025/09/11