Document.createNodeIterator 是高效 DOM 遍历工具,支持按需、单向、只读访问指定节点类型;通过 whatToShow 精确过滤和 acceptNode 细粒度控制,避免预加载与中间数组,性能优于 querySelectorAll 和递归遍历。

Document.createNodeIterator 是一个被低估但极其高效的 DOM 遍历工具,它比递归遍历或 querySelectorAll 更轻量、更可控,特别适合需要**按顺序、单向、只读访问特定节点类型**的场景(如提取纯文本、跳过注释/脚本、构建语义树等)。它的高性能来自底层原生实现和惰性求值——不预先收集全部节点,而是按需返回下一个匹配项。
明确目标节点类型,用 whatToShow 精确过滤
这是性能关键的第一步。不要依赖后续 JavaScript 过滤,而应直接通过 NodeFilter.SHOW_ELEMENT、NodeFilter.SHOW_TEXT 等常量组合设置 whatToShow 参数,让浏览器在遍历时就跳过无关节点类型。
- 只遍历元素节点:
NodeFilter.SHOW_ELEMENT - 只遍历文本节点(含空格、换行):
NodeFilter.SHOW_TEXT - 同时遍历元素和文本(忽略注释、CDATA、处理指令):
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT - 排除脚本和样式内容(安全提取正文):
NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT+ 自定义acceptNode过滤掉<script></script>、<style></style>及其后代
用 acceptNode 实现细粒度、低开销的逻辑控制
acceptNode 是一个可选但强大的回调函数,它在每个候选节点上运行一次,返回 NodeFilter.FILTER_ACCEPT、FILTER_REJECT 或 FILTER_SKIP。相比在循环中手动判断,它与迭代器深度耦合,避免了额外的数组索引或 DOM 查询开销。
生成Blender Python (bpy)脚本,该脚本使用node_groups API和GeometryNodeTree接口程序化地创建几何节点修改器树,用于参数化3D资产生成。
-
FILTER_ACCEPT:返回该节点,并继续向下子树遍历 -
FILTER_SKIP:跳过该节点及其全部子节点(例如遇到<nav></nav>或<aside></aside>时整块跳过) -
FILTER_REJECT:跳过该节点,但继续遍历其子节点(适合“屏蔽容器但保留内容”,如隐藏<div class="ad-banner"> 但提取其中的文字) <p>示例:跳过所有 <code>script、style元素及其后代:const iter = document.createNodeIterator( document.body, NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_TEXT, { acceptNode(node) { if (node.nodeType === Node.ELEMENT_NODE) { if (node.tagName === 'SCRIPT' || node.tagName === 'STYLE') { return NodeFilter.FILTER_SKIP; } } return NodeFilter.FILTER_ACCEPT; } } );用 nextNode() 按需驱动,避免预加载和内存堆积
NodeIterator 不生成数组,
nextNode()每次只计算并返回下一个符合条件的节点。这对长文档、动态内容或内存敏感环境(如 WebView、低端设备)至关重要。- 无需缓存全部结果,适合流式处理:逐个提取文本、实时高亮、增量解析
- 可随时中断(
break或return),无资源泄漏风险 - 配合
while (node = iter.nextNode()) { ... }结构清晰,语义明确 - 注意:多次调用
nextNode()会推进内部指针,不可回退;如需重用,应新建迭代器
对比传统方式:为什么它更高效
相较于
document.querySelectorAll('*')+ 循环判断,或递归childNodes:- 零中间数组分配 —— 无
[]创建、无push开销 - 原生 C++ 层过滤 ——
whatToShow在底层完成类型判断,快于 JS 层node.nodeType === Node.ELEMENT_NODE - 天然深度优先、前序遍历 —— 行为确定,无需手动维护栈或队列
- 对 Shadow DOM 友好(若传入 shadowRoot 作为根节点),且默认不穿透,可控性强


















