jQuery 选择器优化

Posted

技术标签:

【中文标题】jQuery 选择器优化【英文标题】:jQuery selector optimization 【发布时间】:2011-08-27 01:53:58 【问题描述】:

在选择器的右侧要具体,在左侧不太具体。

// unoptimized
$('div.data .gonzalez');

// optimized
$('.data td.gonzalez');

Quote Source

    有人能解释一下为什么不那么具体的左侧作为 CSS 选择器会更快吗?

    这是 Sizzle 的事情还是同样适用于 document.querySelectorAll

    在 CSS 文件中使用“类似优化”的 CSS 选择器是否有任何速度提升?

【问题讨论】:

我猜这是错的,不是吗?从很多中选择很多,然后从这个很多中选择一点比从很多中选择一点然后从这个小中选择很多更昂贵。 @ariel:Sizzle(jQuery 选择器引擎)是一个有趣的野兽。有时,表面上看起来很明显的事情实际上并不真实。我似乎记得 Sizzle 有时会(显然是出于充分的理由)由内而外地工作——例如,首先找到 td.gonzalez,然后查看它是否在 .data 内。但我怀疑就像大多数概括一样,它可能是错误的,也可能是正确的,这取决于具体情况(例如,divtd 元素的数量)。 第二个版本是否优化很大程度上取决于你的 html 如有疑问,请使用 jsperf.com @Gary:根据您使用的浏览器,它会有很大差异。如果您使用的是现代浏览器,它将具有querySelectorAll,并且您可能不会注意到任何差异,因为它全部位于浏览器引擎的内部。但是,如果您使用的是 IE6 或 IE7,您会注意到一个很大的差异(在综合测试中;这是否会转化为现实世界的差异完全是另一回事)。试试这个,例如,在 IE7 中:jsperf.com/specific-left-or-right 更具体的右侧很容易获胜。但这都是微优化。 【参考方案1】:

jQuery 的 Sizzle 引擎从右到左解析选择器,这是真的。但是也有例外,例如当第一个操作数是 ID 时。然后搜索将在具有此 ID 的元素的上下文中进行。这是 Sizzle Engine 的特殊性,但我不知道 querySelectorForAll 是如何实现的。

一个例子:

$('div.data .gonzalez');

Sizzle 将获取所有带有 gonzalez 类的 DOM 元素,然后检查每个祖先是否是带有类数据的 div 标签

【讨论】:

【参考方案2】:

这本书顺便提到了这一点,但我相当肯定建议是针对 Sizzle(jQuery 选择器引擎)的,而不是一般的。您的里程可能会有所不同,但实现 querySelectorAll 的浏览器不太可能显示出真实世界的差异。

Sizzle 在适当的时候由内而外地工作,因此可能会查找td.gonzales,然后查看它是否在.data 内,而不是相反。我记得当 Sizzle 第一次出现时,这有点令人惊讶,但实际上效果更好。因此,您可以了解为什么后代选择器的右侧越具体越好。

Here's a test case,在 IE7 中尝试一下,您会看到对更具体的右侧的明显偏好。但是在现代浏览器中尝试一下,您应该看起来基本没有区别。

不过,这都是微优化,在没有实际问题需要解决的情况下几乎毫无用处,因为它会根据您页面上的元素而显着变化。记住你是否真的有一个缓慢的选择器会在旧浏览器上给你带来麻烦,这很有用,但除此之外......

【讨论】:

那本书确实应该提到 Sizzle 从右到左阅读。这对我来说不是常识。我知道这是一个微优化,很难理解为什么从左到右会更快。如果需要,了解如何优化选择器很有用。 @Raynos:嗯,我很确定它不会总是。但我认为(认为,请注意)它适用于后代选择器,除非它可以使用 ID 锚定自身。

以上是关于jQuery 选择器优化的主要内容,如果未能解决你的问题,请参考以下文章

jQuery 优化多个选择器

高性能jquery的几种优化

jQuery学习笔记之选择器

如何使用 jQuery 日期选择器优化引导输入标签

哪个 jQuery 多元素选择器优化得更好

如何优化 jQuery tag:contains() 选择器?