getElementsByTagName とは何か
getElementsByTagName は、指定したタグ名(例: “div”, “p”, “a”)を持つ要素をまとめて取得するメソッドです。返り値は HTMLCollection(ライブコレクション)で、DOM が後から増減すると内容が自動的に更新されます。ここが重要です:ライブであるため、ループ中に対象が増減すると挙動が変わる可能性があります。処理を安定させたいなら、取得直後に配列へ固定化してから扱うのが安全です。
基本の使い方(全ての同種タグを一括取得)
ドキュメント全体から取得
<div>One</div>
<div>Two</div>
<p>Paragraph</p>
<script>
const divs = document.getElementsByTagName("div"); // HTMLCollection(ライブ)
console.log(divs.length); // 2
console.log(divs[0].textContent); // "One"
</script>
HTML親要素を起点に範囲を絞って取得
<section id="panel">
<div>Panel A</div>
<div>Panel B</div>
</section>
<div>Outside</div>
<script>
const panel = document.getElementById("panel");
const innerDivs = panel.getElementsByTagName("div"); // panel配下のみ
console.log(innerDivs.length); // 2(Outside は含まれない)
</script>
HTMLここが重要です:document からの取得はページ全体が対象になります。意図しない混入を避けるには、親要素からの取得でスコープを限定しましょう。
ライブ HTMLCollection の挙動(増減に自動追随)
取得後に要素を追加すると件数が増える
const divs = document.getElementsByTagName("div"); // 2件とする
const d = document.createElement("div");
d.textContent = "New";
document.body.append(d);
console.log(divs.length); // 3(ライブなので自動で増える)
JavaScript反復処理中の落とし穴(対象が縮む・広がる)
const ps = document.getElementsByTagName("p");
// 悪い例:ループ中にタグを置き換えると集合が変わる可能性
for (let i = 0; i < ps.length; i++) {
const p = ps[i];
const span = document.createElement("span");
span.textContent = p.textContent;
p.replaceWith(span); // ここで p が消える → ps.length が変化する
}
JavaScriptここが重要です:ライブコレクションを直接いじりながら走査すると、インデックスがずれて要素を飛ばすことがあります。最初に配列へ固定化して処理するか、ループ開始前に長さを変数へキャプチャして固定長で回しましょう。
配列として扱うコツ(安定さ・可読性を高める)
取得直後に配列へ固定化
const divsLive = document.getElementsByTagName("div");
const divs = Array.from(divsLive); // 静的な配列へ
divs.forEach(el => el.classList.add("processed"));
JavaScript変換・絞り込み・集計が書きやすくなる
const titles = Array.from(document.getElementsByTagName("h2"))
.map(el => el.textContent.trim())
.filter(text => text.length > 0);
JavaScriptここが重要です:map / filter / reduce といった配列メソッドを使うなら、必ず配列化。処理途中で DOM が変わっても結果がブレません。
仕様のポイント(タグ名の大小・ワイルドカード・名前空間)
HTML 文書ではタグ名の大小は区別されません。”DIV” でも “div” でも同じ結果になります。一方、XML/SVG では大小が区別されることがあります。ワイルドカード “*” を指定すると、範囲内の全要素を取得できます(用途は限定的ですが、要素総数の確認や一括走査で便利です)。
document.getElementsByTagName("*"); // すべての要素(HTMLCollection)
document.getElementsByTagName("DIV"); // HTMLでは "div" と同じ
JavaScriptここが重要です:普段の HTML では小文字で統一すると読みやすく、SVG など名前空間要素を扱うときはタグ名の大小に注意しましょう。
querySelectorAll との使い分け(柔軟性と最新性の比較)
querySelectorAll は CSS セレクタで柔軟に取得でき、返り値は静的 NodeList(後から DOM が変わっても結果は固定)。getElementsByTagName はタグ名だけで高速に取得でき、返り値はライブ HTMLCollection(常に最新)。複雑な条件で絞る、配列メソッドを多用する、処理の安定性を優先するなら querySelectorAll。常時最新の集合を監視したい、タグ単位で広く取って後続処理で判定するなら getElementsByTagName が向いています。
// 静的で安定:タグ+属性まで絞る
const nodes = document.querySelectorAll("div.card[data-active='true']");
// 最新性重視:タグ単位で常時更新される集合
const divs = document.getElementsByTagName("div");
JavaScriptここが重要です:日常的な UI 処理では静的のほうがバグが少なく、読みやすいことが多いです。ライブは「最新性」に価値がある場面に絞ると扱いやすくなります。
タイミングとパフォーマンス(安全に速く扱う)
DOM 構築前に取得すると null や空集合になることがあります。defer でスクリプトを読み込み、DOM 構築完了直前の安全なタイミングで初期化すると安定します。また、読み取りと書き込みをバッチ化し、見た目の変更はクラス切り替えを基本にすると、再描画コストを抑えられます。
<script src="app.js" defer></script>
HTMLここが重要です:いつ触るか(defer / DOMContentLoaded)、どう変えるか(クラスで一括)を意識するだけで、体感速度と安定性が大きく向上します。
実践例:記事カードの要約を一括整形
<section id="articles">
<article><h2>タイトルA</h2><p>説明文A ...</p></article>
<article><h2>タイトルB</h2><p>説明文B ...</p></article>
</section>
<script defer>
const section = document.getElementById("articles");
const articles = Array.from(section.getElementsByTagName("article")); // 固定化
articles.forEach(el => {
const title = el.getElementsByTagName("h2")[0]?.textContent.trim() || "無題";
const desc = el.getElementsByTagName("p")[0]?.textContent.trim() || "";
el.classList.add("card");
el.setAttribute("data-title", title);
el.setAttribute("data-length", String(desc.length));
});
</script>
HTMLここが重要です:親要素からの範囲取得でスコープを限定し、ライブ集合は配列化して安定処理。内部のタグも getElementsByTagName で素直に取れますが、存在しない可能性に備えて安全な参照([0]?)を徹底しましょう。
まとめ
getElementsByTagName は「タグ名で要素を一括取得」する高速な入り口で、返り値はライブ HTMLCollection。最新性が魅力ですが、反復中の変動でバグが起きやすいため、配列化して固定してから処理するのが安全です。HTML ではタグ名の大小を区別しない、”*” で全要素を取得できる、親要素からの取得でスコープを絞れる——この要点を押さえつつ、複雑な条件や安定した処理が欲しい場合は querySelectorAll を使い分けましょう。タイミングは defer/DOMContentLoaded に合わせ、更新はクラス切り替え中心に。これが、タグベース取得を速く・正確・壊れにくく運用するコツです。
