20241102-检测dom节点中子节点

判断一个 DOM 元素(dom1)是否在另一个元素(dom2)内部,有多种方法,以下是常用方案、实现原理及性能对比

一、常用方法

1. Node.contains()(最推荐,性能最好)

这是 DOM 原生提供的专门用于判断节点包含关系的方法,简洁且高效。

语法

1
dom2.contains(dom1)
  • 返回值:true(包含)或 false(不包含)。
  • 特点:
    • 不仅判断子元素,还包括后代元素(如孙子节点);
    • dom1 === dom2(同一个元素),也返回 true
    • 适用于所有节点类型(元素节点、文本节点等)。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="parent">
<div id="child">
<span id="grandson"></span>
</div>
</div>

<script>
const parent = document.getElementById('parent');
const child = document.getElementById('child');
const grandson = document.getElementById('grandson');
const other = document.getElementById('other');

console.log(parent.contains(child)); // true
console.log(parent.contains(grandson)); // true
console.log(parent.contains(parent)); // true(自身也包含)
console.log(parent.contains(other)); // false
</script>

2. Node.compareDocumentPosition()

通过位掩码判断两个节点的关系,功能更强大(可判断包含、前后位置等),但代码稍复杂。

语法

1
(dom2.compareDocumentPosition(dom1) & Node.DOCUMENT_POSITION_CONTAINED_BY) !== 0
  • compareDocumentPosition() 返回一个数字(位掩码),通过与 Node.DOCUMENT_POSITION_CONTAINED_BY(值为 16)进行按位与运算,判断 dom1 是否被 dom2 包含。

示例

1
const isContained = (dom2.compareDocumentPosition(dom1) & 16) !== 0;

3. 手动遍历父节点(兼容性最好)

通过循环向上查找 dom1 的父节点,直到找到 dom2 或到达 document 顶层。

实现代码

1
2
3
4
5
6
7
8
function isContained(dom1, dom2) {
let current = dom1;
while (current) {
if (current === dom2) return true;
current = current.parentNode; // 向上遍历父节点
}
return false;
}
  • 特点:兼容性极好(支持所有浏览器),但性能不如原生方法。

4. 其他方法(有局限性,不推荐)

  • **Element.closest()**:需通过选择器匹配,若 dom2 无唯一选择器则不便使用:
    1
    dom1.closest('#dom2-id') === dom2;
  • **document.querySelector()**:通过 dom2.querySelector() 查找,但需 dom1 有唯一标识(如 id),灵活性差:
    1
    dom2.querySelector('#dom1-id') !== null;

二、性能对比

通过 JSBench 等工具测试(以现代浏览器 Chrome/Firefox 为例),性能排序如下:

方法 性能评级 说明
Node.contains() ⭐⭐⭐⭐⭐ 性能最好,原生底层实现,直接返回结果,无额外遍历。
Node.compareDocumentPosition() ⭐⭐⭐⭐ 性能接近 contains(),但因需位运算,稍慢一丢丢。
手动遍历父节点 ⭐⭐⭐ 需 JS 循环遍历,DOM 层级越深性能越差,仅在兼容老浏览器时考虑。

三、总结与建议

  • 首选方案Node.contains()简洁、高效、兼容性好(IE9+ 及所有现代浏览器均支持)。
  • 特殊场景:若需同时判断节点的其他位置关系(如谁前谁后),可使用 compareDocumentPosition()
  • 兼容老浏览器:若需兼容 IE8 及以下,再考虑手动遍历父节点。

20241102-检测dom节点中子节点
http://example.com/20241102-检测dom节点中子节点/
作者
csorz
发布于
2026年2月25日
许可协议