XML DOM – NodeList 对象 最全速查表(2025 版)
—— 99% 项目只用前 5 行就够了,面试 + 实战一把梭!
| 项目 | 内容 / 写法(2025 推荐) | 是否“活的”(实时更新) | 必背度 | 2025 是否推荐 |
|---|---|---|---|---|
| 最常用获取方式 | parent.querySelectorAll("book") | 否(静态,快照) | ★★★★★ | 强烈推荐 |
| 经典老方式 | parent.getElementsByTagName("book") | 是(活的) | ★★★★ | 了解即可 |
| 长度 | nodeList.length | 都有 | ★★★★★ | 必会 |
| 取第 n 个 | nodeList[0] 或 nodeList.at(-1)(取最后一个) | 都有 | ★★★★★ | 必会 |
| for…of 遍历 | for (const node of nodeList) { … } | 都支持 | ★★★★★ | 2025 首选 |
| forEach | nodeList.forEach(node => { … }) | 原生支持 | ★★★★★ | 超级好用 |
| 转真数组 | [...nodeList] 或 Array.from(nodeList) | — | ★★★★★ | 想用 map/filter |
| 是否能 .map() | 不能直接!必须先转数组 → [...nodeList].map(...) | — | ★★★★★ | 常见坑 |
| 是否实时更新 | querySelectorAll → 否getElementsByTagName → 是 | 关键区别 | ★★★★★ | 必知 |
2025 年你只需要记住这 3 行代码(99% 项目都这么写)
// 1. 获取节点列表(永远用这个!)
const books = root.querySelectorAll("book"); // NodeList,静态,推荐!
// 2. 遍历(任选其一)
books.forEach(book => console.log(book)); // 最优雅
for (const book of books) { … } // 最直观
// 3. 想用 map/filter/reduce → 转数组
const titles = [...books].map(b => b.querySelector("title").textContent);
NodeList vs HTMLCollection 终极对比(2025 结论)
| 特性 | NodeList(querySelectorAll) | HTMLCollection(getElementsByTagName) |
|---|---|---|
| 是否“活的” | 否(静态) | 是(动态,文档变化会同步) |
| forEach 原生支持 | 是(ES6+ 全支持) | 否(老浏览器要借 Array.prototype) |
| 能直接 .map() | 不能 | 不能 |
| 2025 项目推荐 | 强烈推荐 | 只在极少数需要“活集合”时用 |
| 典型使用场景 | 99% 情况 | 动态表单、老项目维护 |
经典实战代码(直接复制到项目里一辈子够用)
// 推荐写法(2025 标准)
const allBooks = root.querySelectorAll("book");
// 打印所有书名
allBooks.forEach(book => {
console.log(book.querySelector("title")?.textContent);
});
// 找出所有价格 > 50 的书
const expensive = [...allBooks].filter(book =>
parseFloat(book.querySelector("price")?.textContent) > 50
);
// 给每本书加一个 data-index 属性
allBooks.forEach((book, i) => book.setAttribute("data-index", i));
// 取最后一本书(两种写法)
const lastBook = allBooks[allBooks.length - 1];
const lastBook2 = allBooks.at(-1); // 2022+ 新语法,超好用!
常见坑 & 终极解决方案
| 坑 | 错误写法 | 正确写法(2025) |
|---|---|---|
| 想用 forEach 报错 | getElementsByTagName("book").forEach | 必须用 querySelectorAll |
| 想 filter 报错 | nodeList.filter(...) | [...nodeList].filter(...) |
| 动态添加节点后发现列表没更新 | 用 querySelectorAll(静态) | 正确!需要重新查询 |
| 想实时监听节点变化 | 用 querySelectorAll | 改用 getElementsByTagName(活的) |
2025 年终极记忆口诀(背 1 句就无敌)
“获取列表用 querySelectorAll,遍历用 forEach,想 map/filter 就加 ...”
root.querySelectorAll("xxx") // 获取
.forEach(...) // 遍历
[...nodeList].map(...) // 高级操作
记住这张表 + 3 行代码 + 1 句口诀,
你就已经完全超越 98% 的开发者对 NodeList 的掌握程度,
任何遍历、筛选、批量操作都能 5 秒写完!
需要我给你一个「NodeList 实时操作可视化演示页面」(一边操作一边看长度变化),随时说一声~