parentNode 返回任意父节点(含 Document、ShadowRoot 等),parentElement 仅返回 Element 实例,否则为 null;遍历时后者提前终止于非元素节点,更安全限定在标签树。

parentNode 和 parentElement 都用于获取父节点,但它们的返回值类型和行为有关键区别——parentNode 返回任意类型的父节点(包括 Document、DocumentFragment、ShadowRoot),而 parentElement 只返回元素节点(Element 实例),其他情况一律返回 null。这个差异在处理非标准 DOM 结构(如 Shadow DOM、模板内容、XML 文档)时尤为关键。
何时 parentNode 会返回非 Element 节点
以下情况 parentNode 存在但 parentElement 为 null:
- 元素直接位于
<template></template>内部:其 parentNode 是 HTMLTemplateElement,parentElement 为 null; - 文本节点或注释节点的父节点是 Element,但它们自身不是 Element,调用其 parentNode 得到的是父元素,而 parentElement 在文本/注释节点上调用无意义(需注意调用主体);
- Shadow DOM 中,自定义元素内部的子节点,其 parentNode 可能是 ShadowRoot,而 ShadowRoot 不是 Element,因此 parentElement 为 null;
- XML 文档中,某些节点的父节点可能是 XMLDocument 或 DocumentFragment,parentElement 始终不适用。
遍历到根节点时的行为差异
向上遍历 DOM 时,两者终止条件不同:
生成Blender Python (bpy)脚本,该脚本使用node_groups API和GeometryNodeTree接口程序化地创建几何节点修改器树,用于参数化3D资产生成。
-
node.parentNode在到达 Document、DocumentFragment 或 ShadowRoot 时仍返回有效对象,继续调用其 parentNode 才可能得到 null(例如 Document.parentNode === null); -
node.parentElement在遇到非 Element 父节点(如 ShadowRoot、Document)时立即返回 null,遍历提前终止; - 这意味着
while (el = el.parentElement)更安全地限定在元素层级,不会意外进入 Document 或 ShadowRoot——适合只关心“标签树”的场景,比如查找最近的<section></section>或带 data-* 属性的祖先。
编写健壮遍历代码的实用建议
根据目标明确选择:
- 需要确保操作对象一定是 HTML/SVG 元素(如设置 class、调用 querySelector、检查 tagName),优先用
parentElement; - 需要访问完整节点树(如序列化、调试、处理 template/content 插槽),用
parentNode,但务必做类型判断:if (node.parentNode instanceof Element); - 封装通用祖先查找函数时,可提供选项控制是否跳过非元素节点:
function closestParent(node, selector, { includeNonElements = false } = {}) {<br> let parent = includeNonElements ? node.parentNode : node.parentElement;<br> while (parent) {<br> if (parent.matches?.(selector)) return parent;<br> parent = includeNonElements ? parent.parentNode : parent.parentElement;<br> }<br> return null;<br> }
一个易被忽略的边界案例
在 Web Components 中:
<my-element>
#shadow-root
<div id="inner"></div>
</my-element>执行 document.querySelector('#inner').parentElement → null(因为父节点是 ShadowRoot);
而 document.querySelector('#inner').parentNode → ShadowRoot 实例。
若逻辑依赖“有父元素才继续”,用 parentElement 会自然跳过 ShadowRoot;若需进一步访问 shadow host,则必须用 parentNode 并手动取 parentNode.host。

















