Zenn
🎯

JavaScriptのDOM要素取得メソッド完全解説

2025/02/23に公開
2

📘 入門編として、基本的な使い方については以下の記事をご参照ください:
要素を取得する3つのJSメソッド 〜挙動の違いをまとめてみた〜

JavaScriptでDOM要素を取得する際、目的に応じて適切なメソッドを選択することが重要です。
本記事では、各メソッドの特徴と使い分けについて、実装例を交えながら詳しく解説します。

DOM要素取得メソッドの分類

JavaScriptのDOM要素取得メソッドは、以下の3つに大別できます。

  1. 単一要素取得メソッド

    • getElementById:ID指定による取得
    • querySelector:CSS セレクタによる最初の要素取得
  2. 複数要素取得メソッド

    • getElementsByClassName:クラス名による取得
    • getElementsByTagName:タグ名による取得
    • querySelectorAll:CSS セレクタによる全要素取得
  3. 特殊な取得メソッド

    • getElementsByName:name属性による取得
    • closest:最近接の親要素取得

サンプルコード

以下のシンプルなHTMLを例に、各メソッドの動作を確認していきましょう。

<div id="container">
  <h1 class="title">書籍一覧</h1>
  
  <ul class="book-list">
    <li class="book-item" data-category="novel">
      <span class="book-name">小説A</span>
      <span class="status">在庫あり</span>
    </li>
    <li class="book-item" data-category="novel">
      <span class="book-name">小説B</span>
      <span class="status">在庫なし</span>
    </li>
    <li class="book-item" data-category="tech">
      <span class="book-name">技術書A</span>
      <span class="status">在庫あり</span>
    </li>
  </ul>
</div>

メソッド別の特徴と使用法

1. 単一要素取得メソッド

getElementById

最も高速で信頼性の高い要素取得メソッドです。

const container = document.getElementById('container');
console.log(container?.querySelector('.title').textContent); // "書籍一覧"

特徴:

  • ✅ 最高速のパフォーマンス(O(1))
  • ✅ 型安全性(戻り値が単一要素または null)
  • ✅ ブラウザ実装の標準化
  • ❌ ID属性のみ対応

querySelector(単一要素)

より柔軟な要素指定が可能な汎用的なメソッドです。

// 最初の本の名前
const firstName = document.querySelector('.book-name').textContent;

// 在庫ありの最初の本
const firstAvailable = document.querySelector('.book-item .status:contains("在庫あり")');

// 特定のカテゴリーの最初の本
const firstNovel = document.querySelector('.book-item[data-category="novel"]');

特徴:

  • ✅ CSS セレクタによる柔軟な指定
  • ✅ 複雑な条件での要素取得が可能
  • ❌ getElementById と比較して低速
  • ❌ セレクタの複雑さに応じてパフォーマンスが低下

2. 複数要素取得メソッド

getElementsByClassName

動的なDOM更新に対応した要素取得が可能です。

// すべての本のアイテム
const books = document.getElementsByClassName('book-item');

// ステータス要素
const statuses = document.getElementsByClassName('status');
console.log(`ステータス表示数: ${statuses.length}`);

// 配列への変換例
const bookNames = [...document.getElementsByClassName('book-name')]
    .map(el => el.textContent);

特徴:

  • ✅ DOM更新の自動検知
  • ✅ メモリ効率の良いライブコレクション
  • ✅ querySelectorAll より高速
  • ❌ 配列操作には変換が必要

querySelectorAll

最も柔軟な複数要素取得メソッドです。

// カテゴリーで絞り込み
const novels = document.querySelectorAll('.book-item[data-category="novel"]');

// 在庫ありの本
const inStock = document.querySelectorAll('.status:contains("在庫あり")');

// 特定の要素内の名前のみ取得
const names = document.querySelectorAll('.book-item .book-name');

特徴:

  • ✅ 高度なCSSセレクタ対応
  • ✅ 静的なNodeListを返す
  • ✅ モダンなJavaScript機能との親和性
  • ❌ 最も処理速度が遅い

パフォーマンス比較

各メソッドには処理速度と機能面で特徴があります。小規模なWebサイトでは体感的な差はほとんどありませんが、大規模なアプリケーションや頻繁な要素取得が必要な場合は、以下の特徴を意識すると良いでしょう。

メソッド 処理速度 更新検知 戻り値の型 使用例
getElementById 最速 × Element | null ページの主要コンテナの取得
getElementsByClassName 速い HTMLCollection 動的に追加される商品リストの監視
querySelector 普通 × Element | null 複雑な条件での要素の特定
querySelectorAll 遅い × NodeList 条件に合う全要素の取得

処理速度の違いを理解する:

  1. 最速:getElementById

    • 電話帳で電話番号を探すように、IDから直接要素を特定できます
    • 例:1万件の要素があっても、IDがあれば一瞬で見つかります
  2. 速い:getElementsByClassName

    • 本の索引から該当ページを探すように、クラス名から要素を見つけます
    • 例:1万件中10件のクラスを探す場合、全件は見ませんが、ある程度の探索が必要です
  3. 普通〜遅い:querySelector/querySelectorAll

    • 図書館で特定の条件の本を探すように、条件に合う要素を順に確認します
    • 例:「2000年以降に出版された青い表紙の技術書」のように、複数の条件を確認する必要があります

実際の処理速度の差が現れる例:

// 1. 高速な実装(推奨)
const container = document.getElementById('main-container');
const items = container.getElementsByClassName('item');

// 2. 低速な実装(非推奨)
const items = document.querySelectorAll('#main-container .item');

// 実行時間の違い(目安)
// 1の場合:数ミリ秒
// 2の場合:数十ミリ秒〜数百ミリ秒(要素数による)

パフォーマンスを意識すべき場面:

  1. スクロール連動の要素更新

    // 良い実装
    const container = document.getElementById('scroll-container'); // 一度だけ取得
    window.addEventListener('scroll', () => {
        // containerは事前に取得済み
        container.style.opacity = calculateOpacity();
    });
    
    // 悪い実装
    window.addEventListener('scroll', () => {
        // スクロールの度に毎回検索が走る
        const container = document.querySelector('.scroll-container');
        container.style.opacity = calculateOpacity();
    });
    
  2. 大量の要素を処理する場合

    // 良い実装:事前にキャッシュ
    const items = document.getElementsByClassName('item');
    const itemArray = [...items]; // 一度だけ変換
    
    itemArray.forEach(item => {
        // 処理を実行
    });
    
    // 悪い実装:毎回検索
    for (let i = 0; i < 1000; i++) {
        const items = document.querySelectorAll('.item');
        // 毎回全要素を検索することになる
    }
    

使い分けの指針:

  1. getElementByIdを使うべき場合

    • ページ内で一意の要素を取得する場合
    • 高頻度で要素を取得する必要がある場合
    • パフォーマンスが特に重要な場合
  2. getElementsByClassNameを使うべき場合

    • 動的に追加・削除される要素を監視する場合
    • 同じクラスの要素を繰り返し取得する場合
    • 中程度のパフォーマンスが必要な場合
  3. querySelector/querySelectorAllを使うべき場合

    • 複雑な条件で要素を指定する必要がある場合
    • CSSセレクタの柔軟性が必要な場合
    • 一度きりの要素取得の場合

実装パターン別のベストプラクティス

1. 高速な要素取得が必要な場合

// キャッシュを活用した実装
const element = document.getElementById('target');
for (let i = 0; i < 1000; i++) {
    element?.style.color = 'red';
}

2. 動的な要素監視が必要な場合

// ライブコレクションの活用
const elements = document.getElementsByClassName('dynamic');
const observer = new MutationObserver(() => {
    console.log('要素数:', elements.length);
});

3. 複雑な条件での要素取得

// 1. シンプルなセレクタ設計
const books = document.querySelectorAll('.book-item');                    // 👍 良い
const items = document.querySelectorAll('div > ul > li.book-item');      // 👎 避けるべき

// 2. 属性セレクタの活用
const novels = document.querySelectorAll('.book-item[data-category="novel"]');
const techBooks = document.querySelectorAll('.book-item[data-category="tech"]');

// 3. 要素の関係性を考慮
const names = document.querySelectorAll('.book-item > .book-name');      // 直接の子要素
const allSpans = document.querySelectorAll('.book-item span');           // すべての子孫

実践的な使用例:

// 本の検索機能
function findBooks(options = {}) {
    let selector = '.book-item';
    
    if (options.category) {
        selector += `[data-category="${options.category}"]`;
    }
    
    const books = document.querySelectorAll(selector);
    return Array.from(books).map(book => ({
        name: book.querySelector('.book-name').textContent,
        status: book.querySelector('.status').textContent
    }));
}

// 使用例
const novelBooks = findBooks({ category: 'novel' });

エラーハンドリング

各メソッドに共通する堅牢な実装パターンです。

// 型安全な実装
function getElement(selector, context = document) {
    const element = context.querySelector(selector);
    if (!element) {
        throw new Error(`要素が見つかりません: ${selector}`);
    }
    return element;
}

// フォールバック
const title = document.querySelector('.title') ?? document.createElement('div');

まとめ:メソッド選択の判断基準

以下の基準に従って最適なメソッドを選択してください。

  1. 要素の特定方法

    • ID指定 → getElementById
    • クラス指定(動的更新あり) → getElementsByClassName
    • 複雑な条件 → querySelector/querySelectorAll
  2. パフォーマンス要件

    • 最高速必要 → getElementById
    • 動的更新検知必要 → getElementsByClassName
    • 柔軟性重視 → querySelector
  3. 戻り値の型

    • 単一要素 → getElementById/querySelector
    • 複数要素(動的) → getElementsByClassName
    • 複数要素(静的) → querySelectorAll

これらの基準を考慮し、プロジェクトの要件に最適なメソッドを選択することで、効率的で保守性の高いDOM操作の実装が可能となります。

2

Discussion

ログインするとコメントできます