doc.querySelectorAll(' #id元素')与doc.querySelector('#id')之间的性能.querySelectorAll(' element');

时间:2015-02-10 13:21:19

标签: javascript css-selectors selectors-api

我试图找到一个元素:

doc.querySelectorAll('#divContentList article');

它运作良好,但另一位开发人员告诉我,我应该写:

doc.querySelector('#divContentList').querySelectorAll('article');

他说这更好,因为它直接转到#divContentList,然后查找article元素。

我不认为他的解决方案是速度性能最好的,它会搜索元素两次。 我认为querySelectorAll非常棒,可以完成它的工作。

主要问题是,哪一行代码总体上最好?

5 个答案:

答案 0 :(得分:2)

这个问题的答案是:

  • 方法1更快
  • 方法2更快
  • 没有区别

问题是答案可能会随着时间而改变。浏览器供应商倾向于优化大量使用的方法。如果方法1被大量使用,它可能会更快,或者将来更快。

这两种方法看起来都与我相同(使用给定的输入)。如果有一个基本的根本原因,为什么一个应该更快:使用更快的方法。


由于你的第一场比赛是一场比赛,所以总是只有一场比赛。

如果您的查询为".parent .child"且有许多家长没有孩子,则".parent .child" 可能比<{1}}更快。

答案 1 :(得分:2)

感谢Mauricio Soares和他的jsPerf第一个例子:

<div id="divContentList"> <article></article> </div>

确实是第一种方法:
doc.querySelectorAll('#divContentList article');
 如果其中只有一个article,则速度更快。

我已将jsPerf修改为10,然后修改为1000 article,性能差异非常大。 Check it here

<div id="divContentList"> <article></article> ... <article></article> </div>

这将导致我的问题的第二种方法:
doc.querySelector('#divContentList').querySelectorAll('article');
更快

最后,使用getElementById表现的效果略有提升 doc.getElementById('divContentList').querySelectorAll('article');
那是最好的表现

Keith Rousseau正确querySelectorAll从右到左进行评估。

修改

我也发现了querySelectorgetElementById/getElementsByTagName的不同之处。 querySelector返回Static NodeList,而getElementById返回Live NodeList。

我做了另一个test document.getElementById('divContentList').getElementsByTagName('article');
这个蛋糕。差别很荒谬

答案 2 :(得分:1)

querySelectorAll从右到左进行求值,因此第一个将查找页面上的所有文章,然后将其过滤到divContentList下面的文章。我会为id获取getElementById,然后找到下面的文章。

但正如其他人所说,测试它。并在多个浏览器中进行测试。

答案 3 :(得分:0)

您可以使用jsPerf进行此类测试......

我已经使用您的用例here设置了一个简单的性能测试,似乎它们具有相似的性能,“单个”querySelector似乎有点更多的性能,但我不要以为在你的申请中这根本不是问题。

答案 4 :(得分:0)

当然,这是一个老问题,但是偶然发现了这个问题,感觉就像是在权衡一下。提前提醒我一个大注意事项是:这两个语句不是,我认为没有人钻研过。在技​​术上是的同义词。这可以解释总体性能差异。

最简单的示例实际上是YouTube。如果您观看任何视频,都会发现他们实际上在重复ID #content。在我尝试的第一个视频中,加载评论部分后,document.querySelectorAll("#content")实际上返回了大约20个元素。这不符合标准,W3's HTML Validator实际上会告诉您这是无效的HTML。但是,浏览器仍然允许这样做,而不是直接拒绝或修改HTML。

如果您的网站重复使用#divContentList,则您的声明将从所有元素中返回所有article元素;而您的同事只会返回嵌套在找到的#divContentList first 实例中的文章。这可以解释为什么您的同事通常看起来更快(请参阅下文)。就像大多数人已经指出的那样,在所有浏览器中用querySelector替换他的第一个getElementById可能会更快。


除此以外,我同意以下一般想法:“如果您想了解某件产品的性能,只需对其进行测量即可。”但要谨慎构造测试。 Here's an example where the JS engine optimized out the actual test case。我的建议总是在您的实际用例范围内进行测试。有很多话题谈论element.querySelector can actually be slower than document.querySelector的方式;但是,从最近的简短测试来看,我无法复制它。

在此页面本身上使用#sidebar.question-hyperlink之类的ID /类,在所有情况下document.querySelector('<ID>').querySelectorAll('<CLASS>');都胜过document.querySelectorAll('<ID> <CLASS>');

但是,我觉得这很关键,差异从未超过10%到20%。在某个时候,问题变成了“可读性/可写性与性能之间的权衡是否值得”。如果您只执行一次此语句一两次,则差异可能以微秒为单位。对于一般用例,您的原始陈述或同事的陈述都可以。

最后一点,

我不认为他的解决方案在速度性能上是最好的,它会搜索元素两次

如果您想读书,可以研究一下浏览器实际上如何实现这些网页查找方法。查看Firefox的源代码,您会发现“ getElementById”使用哈希表查找,这几乎可以瞬间找到结果。不同供应商的实现方式会有所不同,这就是为什么在许多不同的浏览器上测试站点很重要的原因。