如何高效校验传入的DOM元素节点是否真实存在于DOM中
你当前写的校验方法性能很差,完全没必要这么做。document.querySelectorAll("*")会扫描整个DOM树,拉取页面所有节点生成静态列表,再转成数组做匹配,要是页面DOM节点多(比如复杂后台、长文页面动辄上万节点),每次调用都要走一遍全量遍历,开销非常大。
最优方案:使用原生isConnected属性
这是浏览器专门提供的判断节点是否接入DOM树的属性,读取操作是O(1)复杂度,没有任何遍历开销,性能最好:
function checkIfNodeExists(nodeElement) { // 先兜底校验入参类型,避免传非节点值时抛出错误 return nodeElement instanceof Node && nodeElement.isConnected; }
- 只要是
createElement创建后没挂载到DOM、或者已经从DOM里移除的节点,这个属性都会返回false,完全符合你的校验要求 - 所有现代浏览器都支持这个属性,只有IE不兼容
兼容旧浏览器的降级方案
如果需要兼容IE这类不支持isConnected的环境,可以用document.contains()方法,性能也比全量查询好得多:它内部是短路查找逻辑,不需要生成全量节点列表,开销极低:
function checkIfNodeExists(nodeElement) { return nodeElement instanceof Node && document.contains(nodeElement); }
不同方案的性能差异
- 原全量查询方案:每次调用都要遍历全量DOM、生成节点列表、转数组匹配,时间复杂度O(n)(n是页面总节点数),大页面下性能问题明显,不推荐使用
isConnected方案:直接读取节点的原生属性,时间复杂度O(1),是目前效率最高的实现document.contains()方案:原生短路遍历,性能接近O(1),兼容性更好,适合需要适配老旧浏览器的场景
内容的提问来源于stack exchange,提问作者Bernat
相关产品推荐
相关产品推荐

