问题描述
我想将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,div,span]
之类的东西(这个是DFS,但对于这个问题并不重要)。
以下三种最快的方法:
-
querySelectorAll
-
NodeIterator
-
TreeWalker
解决方法
最近我来尝试另外几个。 低于结果时,从最慢到最快,同时指定比最慢的慢。
基于Chrome的结果。 Safari显示的数字大致相同。 Firefox的该perf应用存在问题,未经验证。
方法1(不更改)慢了81%
//Entity Framework
public partial class ApplicationUser : IdentityUser<Guid>
{
...
public virtual ICollection<Message> Messages { get; set; }
}
//Breeze.Sharp Entity
public partial class ApplicationUser : BaseEntity
{
...
public NavigationSet<Message> Messages
{
get { return GetValue<NavigationSet<Message>>(); }
}
}
方法2(传播)慢了约77%
const list = Array.from(root.querySelectorAll('*'));
list.unshift(root);
方法3(NodeIterator)慢32%
const list = [root,...root.querySelectorAll('*')];
方法4(TreeWalker)最快
const list = [];
const ni = document.createNodeIterator(root,NodeFilter.SHOW_ELEMENT);
let next;
while (next = ni.nextNode()) {
list.push(next);
}
奖金(空根检查)慢1%(空根检查快98%)
const list = [root];
const tw = document.createTreeWalker(root,NodeFilter.SHOW_ELEMENT);
let next;
while (next = tw.nextNode()) {
list.push(next);
}
观察和结论
- 数组操作(如果考虑的话)表明,扩展(
const list = [root]; if (root.childElementCount) { const tw = document.createTreeWalker(root,NodeFilter.SHOW_ELEMENT); let next; while (next = tw.nextNode()) { list.push(next); } }
)运算符的方法比...
方法要快 - 主要性能提升来自使用本机迭代器,
unshift
是迄今为止最快的
实施特殊的加速奖励 - 几乎总是是合理的,对于嵌套结构,影响可以忽略不计,但是对于空树,它的运行速度两倍 li>
可以进行基准测试here。