javascript - querySelectorAll vs NodeIterator vs TreeWalker - 最快的纯 JS 平面 DOM 迭代器
问题描述
我想将 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
解决方案
我最近才来尝试其他一些。下面的结果从最慢到最快,同时指定如何比最快慢。
基于 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);
}
}
观察和结论
- 数组运算,如果/当考虑时,表明 spread (
...
) 运算符方式比unshift
方法快 - 主要的性能提升来自使用本机迭代器,
TreeWalker
是迄今为止最快的 - 实现这种特殊的加速奖励几乎总是合理的,对于嵌套结构,影响可以忽略不计,但对于一棵空树,它的运行速度要快两倍
基准测试可以在这里找到。
推荐阅读
- node.js - 我正在通过 mongoose 为数据库编写代码,但在终端 mongoose.connection.on 错误上出现此错误
- jmeter - Jmeter什么时候释放对象?
- sql - 使用 Oracle SQL 读取 XML 命名空间
- php - 无法连接服务器。错误号 2。“错误通知:stream_socket_client(): failed: No such host is known Connection: Failed
- service-worker - 自定义@angular/service-worker
- android - 封闭的 alpha 测试轨道如何区分两个测试轨道?
- sql-server - 将 MAX 中的空值指向 Next Date 的 MIN
- angular - @ngrx/router-store/index 没有导出成员“RouterReducerState”
- mysql - 如何按时间选择?
- javascript - 通过拖动引导列来调整它们的大小