jQueryselect器$('#foo a')是如何评估的?

作为jQuery代码的一个例子( https://coderwall.com/p/7uchvg ),我读到了expression式$('#foo a'); performance如下:

find页面中的每a ,然后过滤里面的#foo

而且看起来效率不高。

那是对的吗? 如果是的话,我们应该如何更好地做到这一点?

这是正确的 – Sizzle(jQuery的select器引擎)的行为方式与CSSselect器相同 。 CSS和Sizzleselect器从右到左进行评估 ,因此#foo a将查找所有节点,然后从#foo a节点进行过滤。

通过确保您的叶子select器具有高度特异性,通常通过给他们一个类或ID,可以改善这一点。

我们应该如何更好地做到这一点?

使用jQuery中的上下文参数。

 $('a', '#foo'); 

现在,jQuery将使用id:foosearch元素上下文中的所有锚点。

在您的查询中,上下文在省略时默认为文档:

 $('#foo a'); == $('#foo a', document); 

在这种情况下,您的查询的确效率不高。

你可以看看这篇文章 。

虽然Sizzle是一个从右到左的引擎(这与css被解释的方式相同),但是你的例子中的特定select器会select页面上的所有锚点元素,然后过滤它们的父元素到匹配“foo”的id。 Sizzle实际上优化了任何以ID开头的select器,并将其用作整个select的上下文,而不是使用文档。 换句话说,你select的select器基本上转化为:

 document.getElementById("foo").getElementsByTagName("a") 

真的,这不是一个糟糕的select。

但是,鉴于jQuery需要做的其他事情(包括循环元素以将它们合并到jQuery实例),jQuery(“#foo”)。find(“a”)总是最快的,因为jQuery实现了一个jQuery对象创build快捷方式为id-onlyselect器,然后它执行从#foo的根发现。

换句话说,当Sizzle("#foo a")Sizzle("a", document.getElementById("foo")) ,但是jQuery("#foo").find... ,Sizzle本身并没有太大的区别jQuery("#foo").find...由于jQuery自己的ID快捷方式会更快。

顺便说一句,我对Sizzle的评论是假设querySelectorAll没有被使用。 如果是这样的话,Sizzle只是把它传递给qsa,这还不如使用jQuery的ID快捷方式。

您可以使用find()来更精细地控制select器顺序:

 $('#foo').find('a'); 

这当然会更复杂的select器,你可以连锁find()和filter()。

对于logging$('#foo').find('a') === $('a','#foo')

[更新]好吧,我后来意识到,这正是你的链接说…

jQueryselect器引擎(Sizzle)去年已被重构,你会在这里find详细的解释: http : //www.wordsbyf.at/2011/11/23/selectors-selectoring/

而不是用a里面的#foo元素进行过滤,只需将一个类附加到a元素上,并获得a$("a.class");a元素$("a.class"); 。 这会更有效率。

又一个“自己尝试”:

  1. jsperf用于10000个元素上的各种select器
  2. jsperf在300个元素上的各种select器
  3. jsperf为“更具代表性的DOM”上的各种select器

与“扁平”DOM(1&2)似乎没有太大的区别,但是嵌套的DOM性能差别更大。

还要注意一些testing用例没有select正确的元素(例如$('.a') vs $('.a', context) ),但是为了比较,我将它们从原始testing中留下。

这个例子将检索名为foo的元素中的所有锚点元素a ,在页面中查找每个a元素,然后筛选里面的#foo,如果您想要selecta #foo

 $("a #foo"); 

这将检索元素内a所有foo元素。