改善jQuery选择器性能的好方法?


74

我正在寻找可以改善jQuery调用选择器性能的任何方式。具体来说是这样的:

$("div.myclass")不是快$(".myclass")

我想可能是这样,但是我不知道jQuery是否足够聪明,可以首先限制标记名的搜索,等等。有人对如何制定jQuery选择器字符串以获取最佳性能有任何想法吗?

Answers:


36

毫无疑问,首先通过标记名进行过滤比通过类名进行过滤要快得多

在所有浏览器都本机实现getElementsByClassName之前,情况就是如此,与getElementsByTagName一样。


但是,即使浏览器实现了该功能,按标记名称进行过滤仍然会更快,对吗?
Hoffmann

我已经从Jeffs的响应中更新了componenthouse.com/article-19以使用最新的jQuery,似乎从第二次测试A和B在Opera 10和firefox 3.5中具有相同的性能。我无法使其在IE8上正常工作(尽管我没有做太多尝试)。因此,我以前的评论似乎不对。
霍夫曼

@hoffmann,可能不是。如果我们假设这两个函数都是用b树实现的,那么我不明白为什么getElementsByClassName会变慢...您仍然必须先建立索引,然后才能使用该函数...
Evan Carroll

@AlienWebguy:这个答案的重点是某些浏览器不支持getElementsByClassName,这意味着页面上的每个元素都需要针对该类进行测试。请记住,这个答案也是在08年给出的。; o)
user113716 2011年

1
@AlienWebguy:您的测试不能准确地表示包含许多DOM元素的大页面。借助于更简单的过滤器集,您的测试更快,而不是更快的查找。
阿伦(Aren)

14

在某些情况下,您可以通过限制查询的上下文来加快查询速度。如果有元素引用,则可以将其作为第二个参数传递,以限制查询的范围:

$(".myclass", a_DOM_element);

应该比

$(".myclass");

如果您已经有a_DOM_element并且它比整个文档小得多。


2
我记得$('.myclass', a_DOM_element)jQuery会转换为/调用,$(a_DOM_element).find('.myclass')因此像在第一个示例那样,简单地使用而不是建立选择器上下文可能会更快。find()
大卫说恢复莫妮卡

5

正如上面的Reid所说,jQuery是自下而上工作的。虽然

这意味着$('#foo bar div')$('bar div #foo')

那不是重点。如果有的#foo话,您将不会在选择器中放置任何内容,因为ID必须是唯一的。

重点是:

  • 如果要从具有ID的元素中选择任何内容,则先选择后者,然后使用.find.children等等:$('#foo').find('div')
  • 您选择器的最左边(第一)部分的效率可能会降低,而缩放到最有效的最右边(最后)部分-这意味着,如果您没有ID,请确保您正在寻找$('div.common[slow*=Search] input.rare')而不是$('div.rare input.common[name*=slowSearch]'),因为这不是。 •始终适用,请确保通过相应拆分来强制选择器顺序。

5

为了完全理解更快的速度,您必须了解CSS解析器如何工作。

传入的选择器使用RegExp分成可识别的部分,然后逐个处理。

一些选择器(例如ID和TagName)使用浏览器的本机实现,该实现更快。而其他类(如类和属性)是分别编程的,因此速度较慢,这需要循环遍历所选元素并检查每个类名。

所以可以回答您的问题:

$('tag.class')比$('。class')更快。为什么?对于第一种情况,jQuery使用本机浏览器实现将选择内容过滤为仅所需的元素。只有这样,它才会启动速度较慢的.class实现,并过滤到您所要求的内容。

在第二种情况下,jQuery使用它的方法通过获取类来过滤每个元素。

由于所有javascript库都基于jQuery,因此它比jQuery传播得更远。唯一的其他选择是使用xPath,但目前并不是所有浏览器都很好地支持它。



3

我要补充说明的是,在99%的Web应用程序中,即使是Ajax繁重的应用程序,Web服务器的连接速度和响应都将提高应用程序而不是JavaScript的性能。我并不是说您应该故意编写速度慢的代码,或者说一般情况下意识到某些事情可能比其他事情更快是不好的。

但是我想知道您是要解决尚未真正存在的问题,还是要针对不久的将来可能发生的变化进行优化(例如,是否有更多的人开始使用支持getElementsByClassName()功能的浏览器)前面提到的),实际上会使优化后的代码运行速度变慢。


3

寻找性能信息的另一个地方是Hugo Vidal Teixeira的选择器性能分析页面。

http://www.componenthouse.com/article-19

这样可以很好地降低ID选择器,类选择器和选择器前缀标记名的速度。

ID最快的选择器是:$(“#id”)

最快的选择器是:$('tag.class')

因此,仅在按班级选择时,按标签前缀才有用!


0

我去过一些jQuery邮件列表,从我在那儿读到的内容来看,它们很可能按标记名和类名进行过滤(反之亦然,如果速度更快)。他们对速度非常着迷,会使用任何东西来获得出色的性能。

除非您以每秒数千次的速度运行该选择器,否则我真的不会为此担心太多。

如果您真的很担心,请尝试做一些基准测试,看看哪个更快。




0

如果我没记错的话,jQuery也是自底向上的引擎。这意味着$('#foo bar div')比慢得多$('bar div #foo')。例如,$('#foo a')将遍历a页面上的所有元素,查看它们的祖先是否为#foo,这使此选择器的效率极低。

Resig可能已经针对这种情况进行了优化(如果他这样做的话,这不会让我感到惊讶-我相信他在他的Sizzle引擎中做到了,但我不确定100%正确。)


0

我相信以ID优先选择总是更快:

$("#myform th").css("color","red");

应该比

$("th").css("color","red");

但是,我想知道以ID开头时有多少链接帮助吗?这是

$("#myform").find("th").css("color","red")
.end().find("td").css("color","blue");

比这快吗?

$("#myform th").css("color","red");
$("#myform td").css("color","blue");

以我的经验,$(“#myform”)。find(“ th”)也比$(“#myform th”)快,因为前者直接委派给浏览器的本机getElementByID。链接也有帮助,但从本质上来说,开销是第二次getElementByID调用的费用,该调用通常很小。
peakxu

嘶嘶声,jQuery的选择器引擎从右到左起作用。因此,您的第一个示例:$(“#myform th”)。css(“ color”,“ red”); 首先找到页面上的所有内容。然后,对这些对象进行迭代,并查看每个对象的父对象,直到找到ID为myForm的元素。理论上讲第二个例子:$(“ th”)。css(“ color”,“ red”); 应该比您的第一个更快,因为那只是遍历th而不检查父母。
克里斯·斯皮茨
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.