news 2026/10/17 15:59:07

深入理解 DOM NodeList:从基础到实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入理解 DOM NodeList:从基础到实战

1. 什么是 NodeList

NodeList 是 DOM 中一个非常重要的集合类型,它表示一组节点的集合。当我们使用document.querySelectorAll()或element.childNodes等 API 时,返回的结果就是 NodeList。

NodeList 与数组(Array)有相似之处,但又有本质区别。理解 NodeList 的特性,对于高效操作 DOM 至关重要。

2. NodeList 的两种类型

NodeList 分为两种类型:静态 NodeList和动态 NodeList(也叫实时 NodeList)。

2.1 静态 NodeList

静态 NodeList 在创建后不会随 DOM 的变化而自动更新。使用document.querySelectorAll()返回的就是静态 NodeList。

// 静态 NodeList 示例 const items = document.querySelectorAll('.item'); console.log(items.length); // 假设当前有 3 个 .item 元素 // 动态添加一个新的 .item 元素 const newItem = document.createElement('div'); newItem.className = 'item'; document.body.appendChild(newItem); // 静态 NodeList 不会自动更新 console.log(items.length); // 仍然是 3,不会变成 4

2.2 动态 NodeList

动态 NodeList 会实时反映 DOM 的变化。使用element.childNodes或document.getElementsByTagName()返回的就是动态 NodeList。

// 动态 NodeList 示例 const div = document.createElement('div'); document.body.appendChild(div); const childNodes = div.childNodes; console.log(childNodes.length); // 0 // 添加子节点后,动态 NodeList 自动更新 const p = document.createElement('p'); div.appendChild(p); console.log(childNodes.length); // 1,自动更新了

3. 获取 NodeList 的常见方式

在 JavaScript 中,有多种方式可以获取 NodeList,下面列举最常见的几种。

3.1 querySelectorAll()

// 获取所有 <p> 元素 const paragraphs = document.querySelectorAll('p'); // 获取所有 class 为 "highlight" 的元素 const highlights = document.querySelectorAll('.highlight'); // 获取所有 id 为 "main" 元素下的所有 <li> const listItems = document.querySelectorAll('#main li');

3.2 childNodes 属性

const container = document.getElementById('container'); // 获取所有子节点(包括文本节点和注释节点) const allChildren = container.childNodes;

3.3 getElementsByTagName()

// 获取所有 <div> 元素(动态 NodeList) const divs = document.getElementsByTagName('div');

4. NodeList 的常用属性和方法

NodeList 提供了几个常用的属性和方法,帮助我们遍历和操作节点集合。

4.1 length 属性

const items = document.querySelectorAll('.item'); console.log(items.length); // 返回 NodeList 中节点的数量

4.2 item() 方法

const items = document.querySelectorAll('.item'); // 获取第一个节点 const firstItem = items.item(0); // 等价于 const firstItem2 = items[0]; console.log(firstItem === firstItem2); // true

4.3 forEach() 方法

const items = document.querySelectorAll('.item'); items.forEach((item, index) => { console.log(`第 ${index} 个元素:`, item.textContent); });

5. 遍历 NodeList 的多种方式

遍历 NodeList 有多种方式,下面逐一介绍。

5.1 使用 for 循环

const items = document.querySelectorAll('.item'); for (let i = 0; i < items.length; i++) { console.log(items[i].textContent); }

5.2 使用 for...of 循环

const items = document.querySelectorAll('.item'); for (const item of items) { console.log(item.textContent); }

5.3 使用 forEach() 方法

const items = document.querySelectorAll('.item'); items.forEach(item => { console.log(item.textContent); });

5.4 转换为数组后使用数组方法

const items = document.querySelectorAll('.item'); // 使用 Array.from() 转换为数组 const itemArray = Array.from(items); itemArray.map(item => item.textContent).forEach(text => console.log(text)); // 或者使用展开运算符 const itemArray2 = [...items]; console.log(itemArray2.filter(item => item.classList.contains('active')));

6. NodeList 与 Array 的区别

NodeList 虽然看起来像数组,但它并不是真正的数组,两者之间存在一些重要区别。

特性NodeListArray
原型NodeList.prototypeArray.prototype
map() 方法不支持(需转换)支持
filter() 方法不支持(需转换)支持
reduce() 方法不支持(需转换)支持
动态性可能是静态或动态始终是静态的
// 验证 NodeList 不是数组 const items = document.querySelectorAll('.item'); console.log(Array.isArray(items)); // false console.log(items instanceof NodeList); // true // 尝试调用数组方法会报错 // items.map(item => item); // TypeError: items.map is not a function

7. 实战案例:批量操作 DOM 元素

下面通过一个完整的实战案例,展示如何利用 NodeList 批量操作 DOM 元素。

7.1 批量修改样式

// HTML: <div class="card">卡片1</div> <div class="card">卡片2</div> const cards = document.querySelectorAll('.card'); cards.forEach(card => { card.style.backgroundColor = '#f0f0f0'; card.style.border = '1px solid #ccc'; card.style.padding = '16px'; card.style.margin = '8px 0'; });

7.2 批量绑定事件

// 给所有按钮绑定点击事件 const buttons = document.querySelectorAll('.btn'); buttons.forEach(button => { button.addEventListener('click', function() { console.log('按钮被点击:', this.textContent); }); });

7.3 动态筛选元素

// 筛选出所有包含特定文本的元素 const allItems = document.querySelectorAll('li'); const filteredItems = Array.from(allItems).filter(item => { return item.textContent.includes('重要'); }); filteredItems.forEach(item => { item.style.color = 'red'; item.style.fontWeight = 'bold'; });

8. 注意事项与最佳实践

在使用 NodeList 时,有几个常见的坑和最佳实践值得注意。

8.1 动态 NodeList 的陷阱

// 动态 NodeList 在遍历时如果修改 DOM,可能导致死循环 const divs = document.getElementsByTagName('div'); // 危险操作:遍历时不断添加新元素会导致无限循环 // for (let i = 0; i < divs.length; i++) { // const newDiv = document.createElement('div'); // document.body.appendChild(newDiv); // } // 安全做法:先转换为静态数组再操作 const divArray = Array.from(divs); divArray.forEach(div => { const newDiv = document.createElement('div'); document.body.appendChild(newDiv); });

8.2 优先使用 querySelectorAll

// 推荐:使用 querySelectorAll 获取静态 NodeList const items = document.querySelectorAll('.item'); // 避免:使用 getElementsByClassName 获取动态 NodeList // 除非你确实需要实时更新的集合 const dynamicItems = document.getElementsByClassName('item');

8.3 使用 Array.from() 转换的时机

// 当需要使用 map、filter、reduce 等数组方法时,先转换 const items = document.querySelectorAll('.item'); const texts = Array.from(items, item => item.textContent); console.log(texts); // 或者使用展开运算符 const itemList = [...items]; const total = itemList.reduce((sum, item) => sum + item.dataset.value, 0);

9. 总结

NodeList 是 DOM 操作中不可或缺的集合类型,掌握它的特性和用法可以显著提升开发效率。本文从 NodeList 的基本概念出发,详细介绍了静态与动态 NodeList 的区别、获取方式、遍历方法、与数组的差异,并通过实战案例展示了批量操作 DOM 的技巧。

在实际开发中,建议根据具体场景选择合适的 NodeList 类型和遍历方式,同时注意动态 NodeList 可能带来的性能问题和遍历陷阱。希望本文能帮助你更好地理解和运用 NodeList。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/17 15:58:39

LabVIEW调用海康HCNetSDK V5.3.6.30实战指南

简介&#xff1a;面向 LabVIEW 开发者的海康威视 HCNetSDK V5.3.6.30 库文件压缩包&#xff0c;用于解决在图形化编程环境中调用海康摄像头 SDK 的问题。资源共 45 个文件&#xff0c;主要以 34 个 DLL 动态链接库和 7 个 LIB 导入库组成&#xff0c;另含 ClientDemo.exe、Read…

作者头像 李华
网站建设 2026/10/17 15:54:07

KBEngine 嵌入式 Python 中的 ensurepip 模块详解:离线引导安装 pip

游戏开发后端 【免费下载链接】kbengine A MMOG engine of server. 项目地址&#xff1a; https://gitcode.com/gh_mirrors/kb/kbengine 点击查看 免费下载 ensurepip 是 CPython 标准库中用于"引导式安装 pip"的模块&#xff1a;它把 pip&#xff08;及其依赖 setu…

作者头像 李华
网站建设 2026/10/17 15:53:51

MapReduce从入门到实战:WordCount带你彻底搞懂Shuffle与调优

先说结论&#xff1a;MapReduce 这个“上古”编程模型&#xff0c;放到今天的大数据面试和离线数仓场景里依然是绕不开的硬骨头。我自己当年从“能跑通 WordCount”到“真看懂 Shuffle 那点事”&#xff0c;中间踩的坑比想象中多得多。这篇东西不打算给你堆概念&#xff0c;就用…

作者头像 李华
网站建设 2026/10/17 15:49:12

OpenCode 进阶指南:用 TaoToken 统一 Key 打通 AI 编码助手工作流

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/10/17 15:48:38

Transformer推理加速实战:从KV Cache到投机采样的10个优化技巧

前阵子帮某个团队调一个生成式模型的线上服务&#xff0c;压测的时候发现吞吐上不去&#xff0c;显存倒是快撑爆了。模型结构没问题&#xff0c;数据链路也正常&#xff0c;问题几乎全出在推理阶段的资源利用上。后来把几个优化手段组合着上&#xff0c;单卡吞吐直接翻了一倍多…

作者头像 李华
网站建设 2026/10/17 15:48:33

自动泊车中的车辆动力学建模与轨迹规划高频考点解析

简介&#xff1a;2022年MathorCup高校数学建模挑战赛C题自动泊车问题赛题原文PDF&#xff0c;面向数学建模参赛者与智能车研究者。题目聚焦城市停车资源紧张背景下的自动泊车技术&#xff0c;要求参赛者依次解决最小转弯半径及动力学分析、泊车过程建模、动态泊车模型构建与实时…

作者头像 李华