nextSibling常返回text节点是因为HTML解析器将标签间空白、换行视作Text节点;应优先使用nextElementSibling或parentElement.children获取元素节点,避免依赖childNodes。

为什么 nextSibling 经常返回 text 节点而不是元素?
因为 HTML 解析器(如浏览器 DOM 或 jsdom)把标签之间的空白、换行都视为 Text 节点。你调用 el.nextSibling 时,大概率拿到的是空格或回车,不是下一个 <div> 或 <p>。
解决办法是跳过非元素节点:
- 用
el.nextElementSibling直接获取下一个兄弟元素(现代浏览器和主流服务端解析器均支持) - 若需兼容极老环境(如 IE8),手动循环:
let sibling = el.nextSibling; while (sibling && sibling.nodeType !== Node.ELEMENT_NODE) { sibling = sibling.nextSibling; } - 注意:
nodeType === 1等价于Node.ELEMENT_NODE,但用常量更可读
如何一次性获取所有同级元素节点(不含文本/注释)?
别用 parentNode.childNodes —— 它包含所有子节点类型。应该用 parentNode.children,它只返回元素节点(HTMLCollection)。
-
children是实时集合,会随 DOM 变化自动更新 - 要转成数组操作(比如
map或filter),得先用[...el.parentNode.children]或Array.from(el.parentNode.children) - 注意:
children不包含DocumentFragment中的节点,也不跨 Shadow DOM 边界
在 jsdom 或 cheerio 中遍历兄弟节点要注意什么?
它们不完全遵循浏览器 DOM 行为。例如 jsdom@20+ 默认启用 pretendToBeVisual,会忽略空白文本节点;而旧版或低配模式下仍会保留。
立即学习“前端免费学习笔记(深入)”;
- 统一建议:优先使用
nextElementSibling/previousElementSibling和parentElement.children,避免依赖childNodes - cheerio 没有
nextElementSibling,改用$(el).next()(返回 cheerio 对象)或$(el).next()[0](取原生 DOM 节点) - 如果用
cheerio.load(html, { xmlMode: true }),换行处理更严格,兄弟遍历结果可能和浏览器不一致
用 for 循环遍历 children 时索引会变吗?
会。如果你在循环中修改了 DOM(比如 remove() 或 appendChild()),children 是实时集合,长度和顺序可能当场变化,导致漏项或重复。
- 安全做法是倒序遍历:
for (let i = el.parentNode.children.length - 1; i >= 0; i--) { const child = el.parentNode.children[i]; // 处理 child } - 或者先缓存:
const children = [...el.parentNode.children];再正向遍历 - 这个坑在服务端批量处理 HTML 片段时特别隐蔽——看起来没动父节点,但插入新元素可能触发重排,间接影响
children列表



















