querySelectorAll vs NodeIterator vs TreeWalker - 最快的纯JS平面DOM迭代器[关闭]

Posted

技术标签:

【中文标题】querySelectorAll vs NodeIterator vs TreeWalker - 最快的纯JS平面DOM迭代器[关闭]【英文标题】:querySelectorAll vs NodeIterator vs TreeWalker - fastest pure JS flat DOM iterator [closed] 【发布时间】:2021-02-09 13:01:16 【问题描述】:

我想将 DOM 树扁平化为 Array。 结果应包括根作为第一个条目。 首选纯 JS 解决方案。 实现这一目标的最快方法是什么?

html结构示例:

<div class="tested-root">
    <span></span>
    <span></span>
    <div>
        <span></span>
        <span></span>
    </div>
    <div>
        <span></span>
        <span></span>
    </div>
</div>

预期的输出是: [div.tested-root, span, span, div, span, span, div, span, span] 或类似的(这个是 DFS,但为了这个问题并不重要)。

从以下三种方法中哪个最快:

querySelectorAll NodeIterator TreeWalker

【问题讨论】:

请添加一个带有所需数组输出的简单 HTML 树。并向我们​​展示您之前尝试过的内容。 What topics can I ask about here?, How do I ask a good question? 【参考方案1】:

我最近才来尝试其他一些。 下面是从最慢到最快的结果,同时指定一个比最快的慢。

基于 Chrome 的结果。 Safari 显示的数字大致相同。 Firefox 与该性能应用程序存在问题,未经过验证。

方法 1(不移位)~81% 慢

const list = Array.from(root.querySelectorAll('*'));
list.unshift(root);

方法 2(传播)~77% 慢

const list = [root, ...root.querySelectorAll('*')];

方法 3(NodeIterator)~32% 慢

const list = [];
const ni = document.createNodeIterator(root, NodeFilter.SHOW_ELEMENT);
let next;
while (next = ni.nextNode()) 
    list.push(next);

方法 4(TreeWalker)最快

const list = [root];
const tw = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
let next;
while (next = tw.nextNode()) 
    list.push(next);

奖励(空根检查)慢约 1%(空根快约 98%)

const list = [root];
if (root.childElementCount) 
    const tw = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
    let next;
    while (next = tw.nextNode()) 
        list.push(next);
    

观察与结论

数组运算,如果/当考虑时,表明传播 (...) 运算符方式比 unshift 方法快 主要性能提升来自使用本机迭代器,TreeWalker 是迄今为止最快的 实现这种特殊的加速奖励几乎总是是合理的,对于嵌套结构,影响可以忽略不计,但对于空树,它的运行速度 两倍 快李>

可以在here找到基准测试。

【讨论】:

“有更好的想法吗?” - 为什么方法 2 与您的问题中的方法完全相同? 为了完整起见 - 比较假定至少比较了 2 个操作数,因此将其添加为基础。 那个“比较”是没有意义的。这取决于文档的结构、浏览器、浏览器版本、浏览器内部结构、进行测量的程序/客户端、程序运行的硬件…… 然后将所有这些变量添加到您的“答案”中... 在大型 DOM 树(>5k 元素)上,使用 NodeIterator 时,我的性能大大提高(快了约 4 倍)。

以上是关于querySelectorAll vs NodeIterator vs TreeWalker - 最快的纯JS平面DOM迭代器[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

querySelectorAll 和 getElementsBy* 方法返回啥?

querySelectorAll 和 getElementsBy* 方法返回啥?

querySelectorAll 和 getElementsBy* 方法返回啥?

queryAll 和 querySelectorAll 有啥区别

querySelectorAll() 的用法

在动态添加的元素上使用 querySelectorAll