jQuery优化选择器

时间:2011-01-15 13:56:08

标签: jquery optimization

我想知道前几天在jQuery中输入你的选择器时,如果你指定你的选择器非常具体或非常松散,它会对性能产生影响。

E.g

$('$myId .someElement')

$('table#myId > tbody > tr > td > div.someElement');

第二个选项是否会更快或者差异是否可以忽略,例如,当你需要反复找到相同的元素时,.each()

4 个答案:

答案 0 :(得分:5)

更新2:

总结一些其他评论。答案是取决于

jQuery的选择器引擎Sizzle以与CSS相同的方式评估选择器:from right to left。所以一般来说,最好是在右侧非常具体,在左侧不太具体。

但它还取决于HTML的结构以及您想要查找的元素的分散程度。

所以,如果你有

                         a
                         |
                        ...
                         |
                         b
                 -----------------
                 |               |
d d d c c c c c   c c c c c c c c   c c c c c c

然后更具体的是更快$('a b > c'),因为您使用b > c提前减少了元素集,并且不必检查每个a的{​​{1}}继承

然而,如果你有

c

然后 a | ... | b ----------------- | | e e e e e e e e d d c c c c c c e e e e e e 会更快,因为选择器更简单,并且在这种情况下测试$('a c')作为c的孩子是多余的(当然你甚至可以{{1} }})。


原始回答

无论哪一个更快,如果你必须反复访问一个元素,存储对它的引用

b

The first selector seems to be a bit faster(在Chrome 8中)。

在较新的浏览器中(支持$('c')),差异可能不如不支持它的浏览器那么大。

<强>更新

我认为这主要取决于jQuery可以使用多少内置方法。因此假设var $element = $('#myId .someElement'); $('some other selector').each(function() { // access $element here }); 不可用,第一个选择器可以转换为

querySelectorAll

对于第二个选择器,jQuery必须另外检查一个元素是否确实是一个孩子。即还有一些处理过程。

答案 1 :(得分:4)

我会选择:

$('.someElement', '#myId')

由于getElementById是最快的选择器操作,因此您首先过滤内容然后搜索该类。选择器越少,选择的速度就越快(取决于使用后代选择器 - 检查注释!)。 Test基于@Felix测试用例。

编辑:所以要加强这个答案。基于jQuery documentation

  

默认情况下,选择器会执行它们的操作   从DOM开始搜索   文档根目录。但是,一个   可以给出替代上下文   使用可选的秒搜索   $()函数的参数。

因此,当您提供第二个参数(上下文)时,jQuery将首先搜索该元素,然后在其中进行搜索,以便从以下位置进行翻译:

$('.someElement', '#myId')

致:

$('#myId').find('.someElement')

现在的诀窍是,尝试找到实际拥有ID的元素的最近容器并将其设置为 context ,因为ID选择是 最快 即可。现在你会说,为什么不使用第二个已翻译过的,我实际上并不会那么在意,因为第一个更干净而且速度并不慢:

                    $('.someElement', '#myId')                  $('#myId').find('.someElement')
Chrome 8.0.552              36,527                                      37,400
Firefox 3.6.13              17,632                                      19,155

答案 2 :(得分:0)

'#myid .myclass'

1)找到所有具有类myclass的元素 2)对于每个这样的元素,如果你到达#myid祖先,就去它的祖先链并停下来。如果没有这样的祖先,请丢弃该元素。

现在,很可能浏览器会优化此过程,例如:

1)找到#myid元素
2)找到所有具有类myclass并且是#myid元素的后代

的元素
table#myid > tbody > tr > td > div.mylcass

请注意,为ID选择器添加类型选择器前缀无效,因为ID在文档中是唯一的。

#myid > tbody > tr > td > div.mylcass

使用类型选择器为类选择器添加前缀在性能方面更好。因此,如果您知道元素的类型,建议您进行设置。

我不确定那些儿童选择器。我想如果你使用它们会更快。但要快多少?可能是可以忽略的?而且,它看起来很难看。

考虑一下:

#myid td > div.myclass 

如果#myid是一个表元素,并且您没有嵌套表,则此选择器应该与第二个选择器一样快。我会用这个。

答案 3 :(得分:-1)

第二个会更快,因为它确切知道每个步骤要查找的内容。

在这个例子中:

$('table#myId > tbody > tr > td > div.someElement');

如果没有tbody,或没有tr,或没有td(等),它可能会立即从搜索中删除。此外,每个后续步骤都将缩小搜索范围(例如:不在<thead>内搜索)。与此示例相比:

$('#myId .someElement')

这必须扫描 #myId的每个子元素。


编辑:正如FelixKing指出的那样,您的第一个示例$('#myId .someElement')实际上是更快。只是勉强,但仍然,更快,所以我想我应该回应。使用子选择器(>)而不是后代选择器(空格)是最快的遍历方法,因为可能的元素集要少得多。但是,现代浏览器具有高度优化的内置方法,jQuery有时可以使用这些方法,实际上减少了执行时间。因此,正如在这种特殊情况下所看到的那样,“更差”的实际上更好,因为浏览器针对执行特定查询进行了更好的优化。然而,一般情况下,原始点仍然存在,特别是如果您使用的东西无法通过浏览器进行优化(例如,自定义选择器)。