isEqualNode

JavaScript

Node.isEqualNode 可以用于比较当前节点(Node)和指定节点是否是相同的。和 Node.isSameNode 不同,.isEqualNode API 并不需要两个被比较的节点是同一个。只需要满足以下的条件,两个节点就会被认为是相同的:

  1. 两个节点的 nodeType 是相同的;
  2. (省略非 Element 比较的情况,具体细节可以参考 DOM 规范);
  3. 如果节点是 element 的话,那么对 A.isEqualNode(B) 来说,A 中所有的属性,都可以在 B 上找到相同的值(反之亦然);
  4. 两个节点应该有等长的 children
  5. 两个节点的 children 的每个相同位置上的值都是相同的(递归调用 isEqualNode 的定义)。

这里需要说明的几点是:

  1. 在属性判断的时候,并不需要关心顺序:
const first = document.createElement('div');
const second = document.createElement('div');
const id = 'id';
const className = 'className';

first.id = id;
first.className = className;

second.className = className;
second.id = id;

// first: <div id="id" className="className"></div>
// second: <div className="className" id="id"></div>
first.isEqualNode(second); // => true
  1. 属性的判断是直接对值进行比较的,因此 style 的顺序不同会造成结果的不同:
const first = document.createElement('div');
const second = document.createElement('div');

first.style.display = 'block';
first.style.color = 'red';

second.style.color = 'red';
second.style.display = 'block';

// first: <div style="display:block;color:red"></div>
// second: <div style="color:red;display:block"></div>
first.isEqualNode(second); // => false
  1. 属性的比较是顺序无关的,但是 children 的比较是顺序相关的:
const first = document.createElement('div');
const second = document.createElement('div');
const childA = document.createElement('div');
const childB = document.createElement('div');

first.appendChild(childA);
first.appendChild(childB);

second.appendChild(childB);
second.appendChild(childA);

first.isEqualNode(second); // => false
  1. Node 是 Element 的“父类”,除了一般的 DOM 节点之外,节点上的 attributes,节点中的 comment 等也是 Node。这些节点也有 isEqualNode API 可以用于比较。对于一般的 Element 来说,可以简单的认为类型,属性和子节点一样,isEqualNode 就会返回 true

原始的比较算法,可以参考 DOM 规范;MDN 的介绍在这里