提高 jQuery 选择器性能的好方法?

我正在寻找任何可以提高 jQuery 调用的选择器性能的方法。特别是像这样的事情:

$("div.myclass")$(".myclass")

我认为它可能是,但我不知道 jQuery 是否足够聪明,可以首先通过标签名来限制搜索,等等。有人知道如何构造一个最佳性能的 jQuery 选择器字符串吗?

30015 次浏览

我曾经参与过一些 jQuery 邮件列表,从我在那里读到的内容来看,它们很可能按照标记名然后类名进行过滤(如果过滤速度更快的话,反之亦然)。他们痴迷于速度,并且会不惜一切代价来获得一点点的表现。

我真的不会担心它太多,除非你运行该选择器数千次/秒。

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

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

直到所有浏览器本机实现 getElementsByClassName 之前都是这样,getElementsByTagName 就是这种情况。

我要补充一点,在99% 的 Web 应用程序中,即使是 Ajax 很重的应用程序,网络服务器的连接速度和响应都会影响应用程序的性能,而不是 javascript。我并不是说你应该故意编写较慢的代码,或者通常意识到什么东西可能比其他东西更快是不好的。

但是我想知道你是否正在尝试解决一个实际上并不存在的问题,或者即使你正在优化一些可能在不久的将来 改变的东西(比如,如果更多的人开始使用一个支持前面提到的 getElementsByClassName()功能的浏览器) ,使得你优化的代码实际上运行得更慢。

可以考虑使用 Oliver Steele 的 Sequential 库随着时间的推移调用方法,而不是一次调用所有方法。

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

“最终”方法可以帮助您在从最初调用开始的一段时间后调用方法。“顺序”方法允许您在一段时间内对多个任务进行排队。

非常有帮助!

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

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

这为按 id、按类别和选择器前缀标记名称的选择器提供了一个很好的速度运行。

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

类中最快的选择器是: $(‘ tag.class’)

因此,标签前缀只有在按类选择时才有帮助!

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

$(".myclass", a_DOM_element);

应该比

$(".myclass");

如果您已经有一个 _ DOM _ 元素,并且它明显小于整个文档。

下面是如何提高 jQuery 选择器的性能:

  • 尽可能使用 # id 选择(性能测试结果 ~ 250更快)
  • 指定选择范围($('.select', this))

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

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

一些选择器,如 ID 和 TagName,使用浏览器的本机实现,这是更快的。而类和属性等其他类则是单独编程的,因此速度要慢得多,需要遍历选定的元素并检查每个类名。

回答你的问题:

$(‘ tag.class’)比 $(‘ . class’)快。为什么? 对于第一种情况,jQuery 使用本机浏览器实现将选择过滤到您需要的元素。只有这样它才会发射得更慢。类实现过滤到您要求的内容。

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

因为所有的 javascript 库都是基于这个的,所以这比 jQuery 传播得更广。唯一的其他选择是使用 xPath,但是目前它在所有浏览器中都没有得到很好的支持。

我问的一个问题的 好建议: 尽可能使用 标准 CSS 选择器。这允许 jQuery 使用 选择器 API。根据 由 John Resig 执行的测试,这将导致选择器的近本机性能。应该避免使用诸如 :has():contains()之类的函数。

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

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

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

我相信通过 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");

如上所述,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]')——因为这并不总是适用确保通过相应的分裂强制选择器顺序。