nodeiterator 可安全可控地深度优先遍历 dom 文本节点,通过 show_text 标志自动过滤非文本节点,避免递归栈溢出;支持自定义过滤函数排除 script/style 内容或空白文本,比 children/childnodes 递归更简洁可靠。

用迭代器扫描 DOM 中所有文本节点,比手写递归更安全、更可控,也天然支持深度优先顺序。核心是用 NodeIterator 配合过滤器,跳过非文本节点,只暴露你要的 Text 类型。
用 NodeIterator 精准筛选文本节点
NodeIterator 是浏览器原生支持的 DOM 遍历工具,它默认按深度优先顺序逐个返回匹配的节点。只需设置过滤条件为 NodeFilter.SHOW_TEXT,就能跳过元素、注释、属性等其他类型。
- 创建时传入根节点(如
document.body)、显示标志、可选过滤函数和是否扩展实体引用 - 不需要手动递归调用,也不用维护栈或处理子节点循环
- 遍历过程不会因 DOM 深度过大而栈溢出,适合长嵌套结构
示例代码:
const iterator = document.createNodeIterator(
document.body,
NodeFilter.SHOW_TEXT,
null, // 不需要自定义过滤函数
false
);
let node;
while ((node = iterator.nextNode()) !== null) {
if (node.textContent.trim() !== '') {
console.log('文本内容:', node.textContent);
}
}
若需进一步控制——加自定义过滤函数
有时你只想提取“可见且非空”的文本,或排除 script/style 标签里的内容。这时可在第三个参数传入过滤函数,返回 NodeFilter.FILTER_ACCEPT 或 NodeFilter.FILTER_REJECT。
- 函数接收一个节点,可检查其父元素:
node.parentElement?.tagName === 'SCRIPT' - 也可判断文本是否全为空白:
!/\S/.test(node.textContent) - 注意:该函数只对
SHOW_TEXT范围内的节点生效,不影响其他类型遍历逻辑
示例片段:
const filter = function(node) {
const parent = node.parentElement;
if (!parent || ['SCRIPT', 'STYLE'].includes(parent.tagName)) return NodeFilter.FILTER_REJECT;
if (!node.textContent.trim()) return NodeFilter.FILTER_REJECT;
return NodeFilter.FILTER_ACCEPT;
};
const iter = document.createNodeIterator(document.body, NodeFilter.SHOW_TEXT, filter, false);
对比 children + 递归:为什么这里不用递归
文本节点散落在 DOM 树各处,可能夹在两个元素之间,也可能作为深层嵌套元素的直接子节点。若用 children 遍历,会完全漏掉它们;改用 childNodes 虽能拿到,但需层层判断 nodeType === Node.TEXT_NODE,容易写错或遗漏边界情况。
-
children只返回元素节点,对文本节点无效 -
childNodes包含文本、注释、元素,但需手动过滤,递归深度大时风险高 -
NodeIterator抽象了遍历细节,语义清晰,一行配置就锁定目标类型
补充:TreeWalker 也能做,但更重
TreeWalker 和 NodeIterator 都支持深度优先,但它额外提供 parentNode()、firstChild() 等导航方法,适合需要双向移动的场景。对纯扫描文本这种单向任务,NodeIterator 更轻量、性能略优。
- 两者都绕过递归调用栈限制
- 如果后续要从某个文本节点反查其父元素或兄弟结构,再考虑
TreeWalker - 日常文本提取,
NodeIterator足够且推荐










