【发布时间】:2010-09-07 22:54:59
【问题描述】:
我正在寻找可以提高 jQuery 调用的选择器性能的任何方法。具体是这样的:
$("div.myclass") 比 $(".myclass") 快
我想可能是这样,但我不知道 jQuery 是否足够聪明,可以先通过标签名称限制搜索,等等。有人对如何制定 jQuery 选择器字符串以获得最佳性能有任何想法吗?
【问题讨论】:
标签: javascript jquery performance css-selectors
我正在寻找可以提高 jQuery 调用的选择器性能的任何方法。具体是这样的:
$("div.myclass") 比 $(".myclass") 快
我想可能是这样,但我不知道 jQuery 是否足够聪明,可以先通过标签名称限制搜索,等等。有人对如何制定 jQuery 选择器字符串以获得最佳性能有任何想法吗?
【问题讨论】:
标签: javascript jquery performance css-selectors
毫无疑问,先按标签名过滤比按类名过滤要快得多。
在所有浏览器都本地实现 getElementsByClassName 之前,情况都会如此,就像 getElementsByTagName 的情况一样。
【讨论】:
getElementsByClassName,这意味着页面上的每个元素都需要针对该类进行测试.请记住,这个答案也是在 08 年给出的。 ;o)
在某些情况下,您可以通过限制上下文来加快查询速度。如果您有元素引用,则可以将其作为第二个参数传递以限制查询范围:
$(".myclass", a_DOM_element);
应该比
快$(".myclass");
如果您已经有一个 _DOM_element 并且它比整个文档小得多。
【讨论】:
$('.myclass', a_DOM_element) jQuery 转换为/调用$(a_DOM_element).find('.myclass') 所以它可能简单地使用find() 而不是建立一个selector context 稍微快一点在你的第一个例子中。
正如 Reid 上面所说的,jQuery 是自下而上工作的。虽然
这意味着
$('#foo bar div')是一个 比$('bar div #foo')慢很多
这不是重点。如果您有 #foo,则无论如何都不会在选择器中添加任何内容,因为 ID 必须是唯一的。
重点是:
.find、.children 等:$('#foo').find('div')
$('div.common[slow*=Search] input.rare') 而不是 $('div.rare input.common[name*=slowSearch]') - 因为这并不总是适用,请确保通过相应拆分来强制选择器顺序。【讨论】:
为了完全理解什么是更快,您必须了解 CSS 解析器的工作原理。
您传入的选择器会使用 RegExp 拆分为可识别的部分,然后逐个处理。
一些选择器,如 ID 和 TagName,使用浏览器的本地实现,速度更快。而其他像类和属性是分开编程的,因此速度要慢得多,需要遍历选定的元素并检查每个类名。
所以可以回答你的问题:
$('tag.class') 比 $('.class') 更快。为什么? 对于第一种情况,jQuery 使用本机浏览器实现将选择过滤到您需要的元素。只有这样,它才会启动较慢的 .class 实现,过滤到您要求的内容。
在第二种情况下,jQuery 使用它的方法通过抓取类来过滤每个元素。
这比 jQuery 传播得更远,因为所有 javascript 库都基于此。唯一的其他选择是使用 xPath,但目前所有浏览器都不太支持它。
【讨论】:
以下是提高 jQuery 选择器性能的方法:
$('.select', this))【讨论】:
我要补充一点,在 99% 的网络应用程序中,即使是 ajax 重度应用程序,网络服务器的连接速度和响应将推动应用程序的性能,而不是 javascript。我并不是说您应该故意编写慢代码,或者通常意识到哪些事情可能比其他事情更快是不好的。
但我想知道您是否正在尝试解决一个尚不存在的问题,或者即使您正在针对在不久的将来可能更改的某些内容进行优化(例如,如果更多的人开始使用支持前面提到的getElementsByClassName() 功能的浏览器),那么您的优化代码实际上会运行得更慢。
【讨论】:
另一个查找性能信息的地方是 Hugo Vidal Teixeira 的选择器性能分析页面。
http://www.componenthouse.com/article-19
这可以很好地降低按 id 选择器、按类选择器和选择器前缀标记名称的速度。
id 最快的选择器是:$("#id")
按类别最快的选择器是:$('tag.class')
因此,只有在按类别选择时,才能使用标签前缀!
【讨论】:
我一直在一些 jQuery 邮件列表中,从我在那里读到的内容来看,它们很可能按标签名称然后类名称过滤(反之亦然,如果它更快的话)。他们对速度非常着迷,并且会使用任何东西来获得一点性能。
除非您每秒运行该选择器数千次,否则我真的不会太担心它。
如果您真的很担心,请尝试做一些基准测试,看看哪个更快。
【讨论】:
考虑使用 Oliver Steele 的 Sequentially 库随时间调用方法,而不是一次调用所有方法。
http://osteele.com/sources/javascript/sequentially/
“最终”方法可帮助您在从初始调用开始的一段时间后调用方法。 “顺序”方法让您可以在一段时间内对多个任务进行排队。
很有帮助!
【讨论】:
great tip 来自我提出的一个问题:尽可能使用标准 CSS 选择器。这允许 jQuery 使用Selectors API。根据tests performed by John Resig,这导致选择器的性能接近原生。应避免使用:has() 和:contains() 等函数。
根据我的研究,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");
【讨论】: