JavaScript | Web API:DOM 拡張 API - NodeList 操作

JavaScript JavaScript
スポンサーリンク

NodeList は「querySelectorAll が返してくる“要素の集まり”」

まず前提からいきます。
document.querySelectorAll() を使うと、複数の要素が一度に取れます。

const items = document.querySelectorAll(".item");
console.log(items);
JavaScript

この items の正体が NodeList です。

見た目は配列っぽいけれど、
「完全な配列ではない “配列風オブジェクト”」というのがポイントです。

ここをちゃんと理解しておくと、
「for で回す」「forEach を使う」「配列に変換する」などの判断がスムーズになります。


NodeList の基本的な性質を押さえる

配列っぽいけど配列ではない

NodeList は、インデックスでアクセスできます。

const items = document.querySelectorAll(".item");

console.log(items[0]);      // 最初の要素
console.log(items.length);  // 要素数
JavaScript

ここまでは配列と同じです。
ただし、mapfilter などの「配列メソッド」は、そのままでは使えません。

items.map(...); // エラーになる(NodeList には map がない)
JavaScript

この「配列っぽいけど配列じゃない」という中途半端さが、
初心者をよく混乱させます。

forEach は使える(現代ブラウザ)

幸い、今どきのブラウザでは NodeList にも forEach が生えています。

items.forEach((item, index) => {
  console.log(index, item);
});
JavaScript

「全部に同じ処理をしたい」というときは、
まず forEach を思い出してOKです。


例題:複数のボタンに同じイベントを付ける

HTML

<button class="color-btn" data-color="red">赤</button>
<button class="color-btn" data-color="green">緑</button>
<button class="color-btn" data-color="blue">青</button>

<div id="box" style="width:100px;height:100px;background:gray;"></div>

JavaScript

const buttons = document.querySelectorAll(".color-btn");
const box = document.querySelector("#box");

buttons.forEach((btn) => {
  btn.addEventListener("click", () => {
    const color = btn.dataset.color;
    box.style.backgroundColor = color;
  });
});
JavaScript

ここでやっていることは、

querySelectorAll.color-btn を全部取る
NodeList に対して forEach で 1 個ずつ処理を書く
各ボタンの data-color を読んで、box の色を変える

という流れです。

「複数の要素に同じ処理を付ける」というのは、
NodeList の一番典型的な使い方です。


重要ポイント①:NodeList を「配列に変換する」テクニック

Array.from を使う

配列メソッド(map, filter, reduce など)を使いたいときは、
NodeList を配列に変換します。

const items = document.querySelectorAll(".item");
const arr = Array.from(items);

const texts = arr.map(el => el.textContent);
console.log(texts);
JavaScript

Array.from(NodeList) で、
「本物の配列」に変換できる、というのを覚えておくと便利です。

スプレッド構文でも変換できる

const items = document.querySelectorAll(".item");
const arr = [...items];
JavaScript

この書き方もよく使われます。
見た目がスッキリしていて、個人的にはかなり好きなパターンです。


重要ポイント②:静的 NodeList と「ライブ」なコレクションの違い

querySelectorAll の NodeList は「静的」

document.querySelectorAll() が返す NodeList は、
静的(static) です。

つまり、あとから DOM が変わっても、
その NodeList の中身は自動では更新されません。

const items = document.querySelectorAll(".item");
console.log(items.length); // 3 とする

const newItem = document.createElement("div");
newItem.className = "item";
document.body.appendChild(newItem);

console.log(items.length); // 3 のまま(増えない)
JavaScript

「最初に取った時点のスナップショット」として扱うイメージです。

getElementsByClassName などは「ライブ」

一方で、document.getElementsByClassName() などが返すのは
HTMLCollection という別の型で、こちらは ライブ(live) です。

DOM に要素を追加・削除すると、
そのコレクションの中身も自動で変わります。

NodeList と HTMLCollection の違いは少しややこしいですが、
初心者のうちは、

querySelectorAll → NodeList(静的)
getElementsBy◯◯ → HTMLCollection(ライブ)

くらいの理解で十分です。

「とりあえず querySelectorAll を使う」
という癖をつけておけば、大きく困ることはありません。


例題:NodeList を配列に変換して map / filter を使う

HTML

<ul>
  <li class="item">りんご</li>
  <li class="item">バナナ</li>
  <li class="item">みかん</li>
</ul>

JavaScript

const nodeList = document.querySelectorAll(".item");

// 配列に変換
const items = Array.from(nodeList);

// テキストだけの配列にする
const texts = items.map(li => li.textContent);
console.log(texts); // ["りんご", "バナナ", "みかん"]

// 「ん」が含まれるものだけに絞る
const filtered = items.filter(li => li.textContent.includes("ん"));
console.log(filtered); // りんご, みかん の li 要素
JavaScript

ここでのポイントは、

NodeList のままでは map / filter が使えない
Array.from で配列に変換すると、配列メソッドが全部使える

という流れです。

「NodeList → 配列 → map / filter」というパターンは、
DOM 操作でかなり頻出します。


重要ポイント③:for / for…of / forEach の使い分け

forEach:一番読みやすい「全要素に同じ処理」

nodeList.forEach((node, index) => {
  // 処理
});
JavaScript

シンプルで読みやすく、
副作用(イベント登録・スタイル変更など)を書くのに向いています。

for…of:シンプルなループ構文として

for (const node of nodeList) {
  // 処理
}
JavaScript

for...of は、
NodeList のような「反復可能オブジェクト」に対して使えます。

index が不要で、
「とにかく全部回したい」だけなら、
forEach と同じくらい読みやすいです。

古典的な for ループ

for (let i = 0; i < nodeList.length; i++) {
  const node = nodeList[i];
  // 処理
}
JavaScript

昔からある書き方で、
今でもパフォーマンス重視の場面などでは使われます。

初心者のうちは、

「まずは forEach か for…of」
「配列メソッドを使いたくなったら Array.from で配列にする」

くらいの感覚で十分です。


例題:チェックボックスの選択状態をまとめて取得する

HTML

<label><input type="checkbox" name="fruit" value="apple"> りんご</label>
<label><input type="checkbox" name="fruit" value="banana"> バナナ</label>
<label><input type="checkbox" name="fruit" value="orange"> みかん</label>

<button id="show">選択中を表示</button>

JavaScript

const checkboxes = document.querySelectorAll('input[name="fruit"]');
const showBtn = document.querySelector("#show");

showBtn.addEventListener("click", () => {
  const checked = Array.from(checkboxes)
    .filter(cb => cb.checked)
    .map(cb => cb.value);

  console.log("選択中:", checked);
});
JavaScript

ここでの流れは、

NodeList を Array.from で配列に変換
filter で checked なものだけに絞る
map で value の配列にする

という、NodeList 操作の「王道コンボ」です。

このパターンが自然に書けるようになると、
フォーム操作や UI 制御が一気に楽になります。


初心者として NodeList 操作で本当に掴んでほしいこと

querySelectorAll が返すのは NodeList(配列っぽいけど配列ではない)
NodeList には length とインデックスアクセスがあり、forEach も使える
配列メソッドを使いたいときは Array.from や […nodeList] で配列に変換する
querySelectorAll の NodeList は「静的」で、あとから DOM が変わっても自動更新されない
「複数要素に同じ処理をする」場面では、NodeList+forEach が基本パターンになる

まずは、

.item を全部取ってきて、
forEach で背景色を変える
Array.from で配列にして、textContent の配列を作る

といった小さな練習をしてみてください。

「単体の要素」ではなく、
「要素の集まりをまとめて扱う」感覚 が身につくと、
NodeList はただの返り値ではなく、
UI 全体をコントロールするための、頼れる入り口に見えてきます。

タイトルとURLをコピーしました