querySelectorAll はマッチする全要素を NodeList として返すため、取得した要素をループで一括操作する場面が頻繁にあります。一括でクラスを追加する、全要素にイベントを登録する、条件で絞り込むなど、実務で使うパターンを解説します。
この記事でわかること
・NodeList を forEach / for…of でループする方法
・スプレッド構文で配列に変換して filter / map を使う方法
・全要素に一括でクラス追加 / スタイル変更 / イベント登録
・N 番目の要素にアクセスする方法
・NodeList と HTMLCollection の違い
・DOM 変更後に NodeList が更新されない注意点
・NodeList を forEach / for…of でループする方法
・スプレッド構文で配列に変換して filter / map を使う方法
・全要素に一括でクラス追加 / スタイル変更 / イベント登録
・N 番目の要素にアクセスする方法
・NodeList と HTMLCollection の違い
・DOM 変更後に NodeList が更新されない注意点
NodeList をループで処理する
JavaScript(forEach: 最もシンプル)
const items = document.querySelectorAll(".item");
// forEach で全要素を処理
items.forEach(item => {
item.classList.add("active");
});
// インデックスも取得可能
items.forEach((item, index) => {
console.log(`${index}: ${item.textContent}`);
});
JavaScript(for…of)
// for...of: break / continue が使える
for (const item of document.querySelectorAll(".item")) {
if (item.classList.contains("skip")) continue;
item.style.color = "blue";
}
JavaScript(通常の for)
// インデックスが必要 or 逆順ループの場合
const items = document.querySelectorAll(".item");
for (let i = items.length - 1; i >= 0; i--) {
items[i].remove(); // 逆順で削除(順方向だとインデックスがずれる)
}
| ループ | break | continue | インデックス | 推奨度 |
|---|---|---|---|---|
| forEach | 不可 | 不可(return でスキップ) | 第 2 引数 | 最もシンプル |
| for…of | 可能 | 可能 | entries() で取得可能 | 推奨(柔軟) |
| for (i) | 可能 | 可能 | 変数 i | 逆順ループに最適 |
配列に変換して filter / map / reduce を使う
JavaScript(スプレッド構文で配列変換)
const cards = document.querySelectorAll(".card");
// NodeList → 配列に変換
const cardArray = [...cards];
// または: Array.from(cards)
// filter: active クラスを持つ要素だけ抽出
const activeCards = [...cards].filter(c => c.classList.contains("active"));
console.log(activeCards.length);
// map: 各要素のテキストを配列で取得
const texts = [...cards].map(c => c.textContent.trim());
console.log(texts); // ["Card 1", "Card 2", "Card 3"]
// find: 条件に合う最初の要素
const featured = [...cards].find(c => c.dataset.featured === "true");
// some: 条件に合う要素が 1 つでもあるか
const hasError = [...cards].some(c => c.classList.contains("error"));
// reduce: 値の集計
const total = [...document.querySelectorAll(".price")]
.reduce((sum, el) => sum + Number(el.textContent), 0);
NodeList には filter / map がない
NodeList は配列ではないため、
NodeList は配列ではないため、
filter / map / find / reduce を直接使えません。[...nodeList] または Array.from(nodeList) で配列に変換してから使ってください。forEach と entries() だけは NodeList で直接使えます。全要素に一括操作する実務パターン
一括クラス追加 / 削除
JavaScript
// 全 .card に active クラスを追加
document.querySelectorAll(".card").forEach(c => c.classList.add("active"));
// 全 .card から active クラスを削除
document.querySelectorAll(".card").forEach(c => c.classList.remove("active"));
// 全 .card の active を切り替え
document.querySelectorAll(".card").forEach(c => c.classList.toggle("active"));
一括スタイル変更
JavaScript
// 全 .item を非表示
document.querySelectorAll(".item").forEach(el => {
el.style.display = "none";
});
// 特定条件の要素だけ表示
document.querySelectorAll(".item").forEach(el => {
el.style.display = el.dataset.category === "food" ? "" : "none";
});
一括イベント登録
JavaScript
// 全ボタンにクリックイベント
document.querySelectorAll(".delete-btn").forEach(btn => {
btn.addEventListener("click", () => {
btn.closest(".card").remove();
});
});
// ※ 大量の要素には「イベントデリゲーション」の方が効率的
document.querySelector(".card-list").addEventListener("click", (e) => {
const btn = e.target.closest(".delete-btn");
if (btn) btn.closest(".card").remove();
});
一括テキスト変更
JavaScript
// 全 .price の値を 10% 増し表示に更新
document.querySelectorAll(".price").forEach(el => {
const original = Number(el.textContent);
el.textContent = Math.round(original * 1.1);
});
一括属性変更
JavaScript
// 全外部リンクに target="_blank" を追加
document.querySelectorAll('a[href^="http"]').forEach(link => {
link.setAttribute("target", "_blank");
link.setAttribute("rel", "noopener noreferrer");
});
// 全 input を disabled にする
document.querySelectorAll("input").forEach(input => {
input.disabled = true;
});
N 番目の要素にアクセスする
JavaScript(インデックスアクセス)
const items = document.querySelectorAll(".item");
// 最初の要素
const first = items[0];
// 最後の要素
const last = items[items.length - 1];
// 3 番目の要素(0 始まり)
const third = items[2];
// CSS の :nth-child でも取得可能
const second = document.querySelector(".item:nth-child(2)");
NodeList と HTMLCollection の違い
| 項目 | NodeList(querySelectorAll) | HTMLCollection(getElementsBy…) |
|---|---|---|
| 更新性 | 静的(取得時点のスナップショット) | ライブ(DOM 変更が即座に反映) |
| forEach | 直接使える | 使えない(Array.from が必要) |
| ループ中のクラス変更 | 安全(静的なので影響なし) | 危険(ライブで中身が変わりスキップ発生) |
| 返すメソッド | querySelectorAll | getElementsByClassName / getElementsByTagName |
JavaScript(ライブコレクションの罠)
// NG: getElementsByClassName はライブ
const items = document.getElementsByClassName("old");
for (let i = 0; i < items.length; i++) {
items[i].classList.replace("old", "new");
// ← items からリアルタイムに消えるため、次の要素がスキップされる!
}
// OK: querySelectorAll は静的
document.querySelectorAll(".old").forEach(el => {
el.classList.replace("old", "new"); // 安全
});
ループ中にクラスを変更するなら querySelectorAll を使う
getElementsByClassName が返す HTMLCollection は DOM の変更がリアルタイムに反映されるため、ループ中にクラスを変更すると要素がスキップされるバグが起きます。querySelectorAll の静的 NodeList ならこの問題は発生しません。
getElementsByClassName が返す HTMLCollection は DOM の変更がリアルタイムに反映されるため、ループ中にクラスを変更すると要素がスキップされるバグが起きます。querySelectorAll の静的 NodeList ならこの問題は発生しません。
DOM 変更後の再取得の注意
JavaScript(静的 NodeList の注意点)
// querySelectorAll は取得時点のスナップショット
const items = document.querySelectorAll(".item");
console.log(items.length); // 3
// DOM に新しい要素を追加
document.querySelector(".list").innerHTML += '<div class="item">New</div>';
// NodeList は更新されない!
console.log(items.length); // まだ 3(4 ではない)
// 再取得が必要
const updatedItems = document.querySelectorAll(".item");
console.log(updatedItems.length); // 4
DOM を変更したら NodeList を再取得
querySelectorAll の NodeList は静的なので、DOM に要素を追加・削除しても自動更新されません。DOM 変更後に最新の状態が必要な場合は再度 querySelectorAll を実行してください。
querySelectorAll の NodeList は静的なので、DOM に要素を追加・削除しても自動更新されません。DOM 変更後に最新の状態が必要な場合は再度 querySelectorAll を実行してください。
実務パターン集
パターン(1): タブ切り替え
JavaScript
document.querySelectorAll(".tab-btn").forEach(btn => {
btn.addEventListener("click", () => {
// 全タブを非アクティブに
document.querySelectorAll(".tab-btn").forEach(b => b.classList.remove("active"));
document.querySelectorAll(".tab-panel").forEach(p => p.hidden = true);
// クリックされたタブをアクティブに
btn.classList.add("active");
document.querySelector(btn.dataset.target).hidden = false;
});
});
パターン(2): フィルタリング(カテゴリで絞り込み)
JavaScript
function filterProducts(category) {
document.querySelectorAll(".product").forEach(p => {
p.hidden = category !== "all" && p.dataset.category !== category;
});
}
パターン(3): チェックボックスの一括チェック
JavaScript
document.querySelector("#check-all").addEventListener("change", (e) => {
document.querySelectorAll('.item-checkbox').forEach(cb => {
cb.checked = e.target.checked;
});
});
パターン(4): 要素の一括削除
JavaScript
// .ad クラスの要素を全て削除
document.querySelectorAll(".ad").forEach(ad => ad.remove());
よくある質問
QquerySelectorAll の結果が 0 件のときエラーになりますか?
Aなりません。要素が見つからない場合は空の NodeList(length=0)が返ります。forEach で空の NodeList をループしても何も実行されないだけでエラーにはなりません。
QforEach 内で break したいです
ANodeList の forEach では break は使えません。途中でループを抜けたい場合は
for...of + break を使うか、配列に変換して some()(return true で停止)を使ってください。QquerySelectorAll を jQuery の $() のように使えますか?
A似た使い方ですが、jQuery は結果を jQuery オブジェクトとして返し、メソッドチェーンが可能です。querySelectorAll は素の NodeList を返すため、メソッドチェーンはできません。forEach で 1 つずつ操作する必要があります。
Q大量の要素に forEach でイベントを登録するとパフォーマンスは?
A数十個なら問題ありませんが、数百〜数千個の場合はイベントデリゲーション(親要素に 1 つだけイベントを登録)の方が効率的です。メモリ使用量が抑えられ、動的に追加された要素にも自動対応します。
QNodeList を配列に変換するのは […nodeList] と Array.from() のどちらがいいですか?
Aどちらも同じ結果です。
[...nodeList] の方が短く書けるため広く使われています。Array.from(nodeList, mapFn) は変換と同時に map を適用できるメリットがあります。QquerySelectorAll で動的に追加した要素が取得できません
AquerySelectorAll は呼び出し時点の DOM をスナップショットとして返します。要素を追加した後に再度 querySelectorAll を呼び出せば取得できます。動的要素のイベントにはイベントデリゲーションを使ってください。
まとめ
querySelectorAll で取得した複数要素の操作方法をまとめます。
| やりたいこと | 方法 |
|---|---|
| 全要素をループ | nodeList.forEach(el => { … }) |
| break / continue を使うループ | for (const el of nodeList) { … } |
| 条件で絞り込み | […nodeList].filter(el => 条件) |
| テキストの配列を取得 | […nodeList].map(el => el.textContent) |
| 全要素にクラス追加 | nodeList.forEach(el => el.classList.add(“cls”)) |
| 全要素を非表示 | nodeList.forEach(el => el.hidden = true) |
| 全要素にイベント登録 | nodeList.forEach(el => el.addEventListener(…)) |
| N 番目の要素 | nodeList[n] または querySelector(“:nth-child(n)”) |
| 最初の要素 | nodeList[0] |
| 最後の要素 | nodeList[nodeList.length – 1] |
| 全要素を削除 | nodeList.forEach(el => el.remove()) |
querySelector / querySelectorAll の基本は「querySelector でDOM要素の取得」も併せて参照してください。

