关于javascript:提高jQuery选择器性能的好方法?

关于javascript:提高jQuery选择器性能的好方法?

Good ways to improve jQuery selector performance?

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

$("div.myclass")$(".myclass")快吗

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


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

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


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

1
$(".myclass", a_DOM_element);

应该比

1
$(".myclass");

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


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

that means $('#foo bar div') is a
lot slower than $('bar div #foo')

那不是重点。如果您使用#foo,则由于ID必须是唯一的,因此您不会在选择器中放置任何内容。

重点是:

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

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

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

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

所以可以回答您的问题:

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

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

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


以下是提高jQuery选择器性能的方法:

  • 尽可能通过#id选择(性能测试结果快250个左右)
  • 指定选择范围($('.select', this))

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

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

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

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

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

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


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

但是我想知道您是要解决尚未真正存在的问题,还是要针对不久的将来可能发生的变化进行优化(例如,如果更多的人开始使用支持< x0>函数)。


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

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

应该比

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

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

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

比这快吗?

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

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

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


我提出的一个问题的一个很好的技巧:尽可能使用标准CSS选择器。这允许jQuery使用Selectors API。根据约翰·雷西格(John Resig)进行的测试,选择器的性能接近原生。应避免使用诸如:has():contains()之类的功能。

从我的研究支持中,引入了jQuery 1.2.7,Firefox 3.1,IE 8,Opera 10,Safari 3.1的Selectors API。


考虑使用Oliver Steele的Sequentially库来逐步调用方法,而不是一次调用所有方法。

http://osteele.com/sources/javascript/sequentially/

"最终"方法可帮助您在从初始调用开始的一段时间后调用方法。"顺序"方法使您可以在一段时间内将多个任务排队。

很有帮助!


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

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

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


推荐阅读