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"));
JavaScriptindex を含めて変換(番号付け)
const numbered = Array.from(document.querySelectorAll("#list li"), (li, i) => ({
index: i + 1,
text: li.textContent
}));
JavaScriptNodeList と配列の違いを押さえる
- 型の違い:
- NodeList:
lengthとforEachは使えるが、map/filterはない。 - 配列: すべての配列メソッドが使える。
- NodeList:
- 静的/動的の違い:
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、素直に展開ならスプレッド。
- 動的な増減があるなら、都度再取得か委譲で柔軟に対応する。
