JavaScript 逆引き集 | NodeList を配列に変換

JavaScript JavaScript
スポンサーリンク

NodeList を配列に変換の基本 — Array.from(nodeList) または [...nodeList]

document.querySelectorAll() が返すのは「配列のように見える NodeList」。forEach は使えますが、map/filter など配列メソッドは使えません。配列に変換すると、慣れた配列処理が一式使えるようになります。


変換の二大パターン

<ul id="list">
  <li>A</li><li>B</li><li>C</li>
</ul>
<script>
  const nodeList = document.querySelectorAll("#list li");

  // 1) Array.from
  const arr1 = Array.from(nodeList);              // 配列に変換
  const texts1 = Array.from(nodeList, li => li.textContent); // 第2引数で map 兼用

  // 2) スプレッド構文
  const arr2 = [...nodeList];                     // 配列に展開
  const texts2 = [...nodeList].map(li => li.textContent);
</script>
HTML
  • Array.from: 変換+同時に「各要素への変換関数」を渡せる。
  • スプレッド構文: シンプルに展開してから、map/filter 等を使う。

よく使うテンプレート集

すべての要素にクラスを追加

const lis = document.querySelectorAll("#list li");
Array.from(lis).forEach(li => li.classList.add("active"));
// または [...lis].forEach(...)
JavaScript

テキストを整形して配列で受け取る

const labels = Array.from(document.querySelectorAll(".item"), el => el.textContent.trim());
// 同等: const labels = [...document.querySelectorAll(".item")].map(el => el.textContent.trim());
JavaScript

条件で絞り込んでから処理

const items = [...document.querySelectorAll(".item")];
const long = items.filter(el => el.textContent.length >= 5);
long.forEach(el => el.classList.add("long"));
JavaScript

index を含めて変換(番号付け)

const numbered = Array.from(document.querySelectorAll("#list li"), (li, i) => ({
  index: i + 1,
  text: li.textContent
}));
JavaScript

NodeList と配列の違いを押さえる

  • 型の違い:
    • NodeList: lengthforEach は使えるが、map/filter はない。
    • 配列: すべての配列メソッドが使える。
  • 静的/動的の違い:
    • querySelectorAll の NodeList は「静的」。DOMが後から変わっても自動更新されない。必要なら「再取得」か「イベント委譲」を使う。
    • childNodes の NodeList は「動的」のことがあるが、通常は querySelectorAll を使う前提でOK。

実務でのコツ

  • 一行で取りつつ加工: Array.from(nodeList, mapFn) が読みやすい。
  • パフォーマンス: 大量要素への繰り返し更新はまとめて(DocumentFragment、class切り替え)で負荷を下げる。
  • 範囲を絞る: 親要素からの相対検索で対象を限定すると安全。
const form = document.querySelector("#profile");
const inputs = [...form.querySelectorAll("[name]")];
JavaScript

ありがちなハマりポイントと対策

  • map/filter が直接使えない:
    • 対策: Array.from(nodeList)[...nodeList] に変換してから使う。
  • 追加した要素が配列に反映されない(静的):
    • 対策: 再度 querySelectorAll で取り直すか、処理をイベント委譲に切り替える。
  • ライブコレクションとの混同:
    • 対策: children はライブ。ループ中に変更するとズレるので、先に配列化してから操作する。

練習問題(手を動かして覚える)

<ul id="list">
  <li class="item">Apple</li>
  <li class="item">Banana</li>
  <li class="item">Cherry</li>
</ul>
<button id="add">Add</button>
<script>
  const list = document.getElementById("list");
  const add = document.getElementById("add");

  // 1) NodeListを配列にして連番付け
  const lis = Array.from(document.querySelectorAll("#list li"));
  lis.forEach((li, i) => li.textContent = `${i + 1}. ${li.textContent}`);

  // 2) 追加後に再取得→配列化→datasetにindex
  add.addEventListener("click", () => {
    const li = document.createElement("li");
    li.className = "item";
    li.textContent = "New";
    list.appendChild(li);

    const arr = [...document.querySelectorAll("#list li")];
    arr.forEach((el, i) => el.dataset.index = String(i + 1));
  });

  // 3) 5文字以上の項目だけ強調
  const long = Array.from(document.querySelectorAll("#list li"))
    .filter(el => el.textContent.replace(/^\d+\.\s*/, "").length >= 5);
  long.forEach(el => el.classList.add("long"));
</script>
HTML

直感的な指針

  • 「配列メソッドを使いたい」→ まず NodeList を配列に変換。
  • 一行で変換+加工なら Array.from、素直に展開ならスプレッド。
  • 動的な増減があるなら、都度再取得か委譲で柔軟に対応する。
タイトルとURLをコピーしました