直接用 parent.contains(child) 即可,它返回布尔值,表示 child 是否为 parent 的任意层级后代(含自身);需确保 parent 是元素或文档节点,且 child 已挂载到 dom 中。

直接用 parent.contains(child) 就行,这是现代浏览器的标准方法,简洁、高效、语义清晰。它返回布尔值,true 表示 child 是 parent 的后代节点(包括子、孙、曾孙等任意层级),也包含自身 —— 但注意:parent.contains(parent) 返回 true,这属于规范定义行为。
contains 的基本用法和注意事项
它只接受一个参数(目标节点),调用者必须是元素节点(Element 或 Document),不能是文本节点或文档片段。
- ✅ 正确:
div.contains(span)、document.contains(el) - ❌ 错误:
textNode.contains(el)(报错)、null?.contains()(报错) - ⚠️ 注意:如果
child不在 DOM 树中(比如刚用document.createElement创建但未挂载),contains一律返回false
兼容旧浏览器的 fallback 方案
IE8 及更早版本不支持 contains,Firefox 早期版本也有过短暂不支持期。此时可用 compareDocumentPosition 回退:
该方法返回一个位掩码数字,其中第 5 位(即数值 16)表示“调用者包含目标节点”。所以判断逻辑是:
-
parent.compareDocumentPosition(child) & 16→ 真值即为包含 - 需额外排除
parent === child的情况(因compareDocumentPosition对相同节点返回0)
封装成通用函数可这样写:
function isContained(parent, child) {
if (parent === child) return true;
if (parent.contains) return parent.contains(child);
if (parent.compareDocumentPosition) {
return !!(parent.compareDocumentPosition(child) & 16);
}
// 最终降级:手动向上遍历 parentNode
let node = child.parentNode;
while (node) {
if (node === parent) return true;
node = node.parentNode;
}
return false;
}
常见误用场景提醒
容易出错的地方不是语法,而是逻辑前提:
- 别对尚未插入 DOM 的元素调用 —— 比如
const el = document.createElement('div'); div.contains(el)一定为false - 事件代理中常用来判断点击是否发生在某个区域内部,记得先
event.target是否有效,再做container.contains(target) -
document.body.contains(el)和document.contains(el)效果不同:前者要求el必须在下;后者只要在整份文档中(比如在里)就返回true
和 parentNode 遍历比有什么优势
不用写循环,性能更好(浏览器原生实现),代码更易读。例如判断点击是否落在弹窗外,一行就能搞定:
if (!dialog.contains(event.target)) closeDialog();- 而手动遍历要处理
null、循环终止条件、边界 case,容易漏掉shadowRoot等特殊情况
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











