注意:Jack 已经修复了这篇文章中几乎所有提到的问题——做得太棒了!
我们一直没有谈论 jQuery 1.1 版本选择器的速度,直到我们的发布更接近准备就绪——然而,似乎这个过程已经被加速了。既然已经泄露了,那么让我们来看看 jQuery 的选择器速度。
简而言之:在 jQuery 1.1 中,我们非常努力地让选择器变得非常快。事实上,根据我们所有的测试,我们比任何其他选择器库都更快。在开发 1.1 版本时,Dean Edwards 的 cssQuery 远远超过了任何其他选择器库。它非常全面,而且速度很快。
今天,Jack Slocum 发布了他的新 DOMQuery 选择器库。简而言之:标准被提高了。他的库非常非常快。可能是目前最快的。
然而,在对他的库和我们的库进行比较时,出现了一些错误,我们想澄清一下。(Jack 和 jQuery 都存在错误。)(作为参考,这是我用来进行测试的 比较套件。)
jQuery 完全支持所有属性选择器。
例如,[@foo],[@foo=bar] 等。显著的区别是,在这种情况下,jQuery 使用 XPath 样式的语法。由于 Jack 的测试没有考虑到这一点,因此似乎我们未能通过所有属性选择器测试。
我们的“elem:empty” 运行良好。
您可以看到 Jack 的测试中,所有选择器(除了 DOMQuery)都失败了 :empty——这更多的是因为他将结果与 DOMQuery 进行比较,而 DOMQuery 得到了错误的结果。规范指出,如果元素不包含任何子元素或文本节点,则该元素为空。这似乎没有在这方面得到考虑。
[foo!=bar],:first,:last 不属于任何规范。
……但它们却在测试套件中。顺便说一下,jQuery 确实实现了 :first 和 :last——但没有实现 [foo!=bar](这似乎只存在于 cssQuery 中?)。总而言之,在您没有为此设计的场景下与他人进行比较,这非常奇怪。
span:not(span.hl-code) 会匹配什么?
这是一个奇怪的灰色地带,我还没有看到有人讨论过,规范也没有帮助澄清。结果集应该是所有不具有 hl-code 类的 span——还是什么都没有,因为您已经过滤掉了所有的 span?例如
// Finds nothing in both
span:not(span)
=> []
// Finds spans that don't have a class of 'foo', in both
span:not(.foo)
=> [ <span>, <span>, ... ]
// jQuery's interpretation of the combination:
$("span:not(span.foo)")
=> []
// DOMQuery's interpretation of the combination:
Ext.select("span:not(span.foo")
=> [ <span>, <span>, ... ]
我们完全承认,我们可能在这方面大错特错——但我很想听听其他人的看法,以及他们对规范的理解。
DOMQuery 不考虑重复项。
目前,执行 Ext.select(“div div”) 返回的元素比执行 Ext.select(“div”) 返回的元素更多——而执行 Ext.select(“div div div”) 返回的元素又多于执行 Ext.select(“div”) 返回的元素。事实上,在 JavaScript 选择器库中,考虑重复项是一个巨大的问题——目前,只有 jQuery 能够正确处理。
这方面的一个重要问题是,考虑重复项在计算上可能非常昂贵——因此,DOMQuery 不考虑重复项会给人一种速度提升的印象。例如
// DOMQuery
Ext.select("div").elements.length
=> 246
Ext.select("div div").elements.length
=> 624
Ext.select("div div div").elements.length
=> 523
// jQuery
jQuery("div").length
=> 246
jQuery("div div").length
=> 243
jQuery("div div div").length
=> 239
DOMQuery 不支持多个过滤器:elem.foo[foo=bar] 或 elem.foo.bar
在实现这一点之前,与其他任何库进行比较都毫无意义。构建一个完全能够处理像这样方面(参见:cssQuery、jQuery)的库,需要付出巨大的代价。(无论是代码大小还是速度代价。)
DOMQuery 的 #id 选择器不检查上下文
如果您尝试执行如下查询
Ext.select("div #badid").elements
=> [div#badid]
您会得到一个 id 为“badid”的元素——即使该元素实际上不在 div 内部。由于 DOMQuery 代码中没有进行有效性检查,因此速度非常快——但结果是错误的。
我应该提到,直到 1.1,jQuery 在这方面也是错误的,所以这是一个很容易被忽视的问题。
根元素去哪儿了?
您会发现,在 DOMQuery 中搜索“html”和“*”时,缺少一个显而易见的东西:HTML 元素。从所有查询中排除根 DOM 元素似乎有点奇怪;特别是考虑到这完全有效:“html > body *”。
……为了公平起见——这里有一个关于我们的 :-)
我们的 :nth-child(even/odd) 有缺陷。
目前它似乎只选择一个元素(!?)。我创建了一个 工单,它应该在周日发布的 1.1 版本中得到解决。
总而言之,很高兴看到 DOMQuery 取得的速度飞跃。选择器速度是一个真正值得竞争的领域;每次有新的速度提升,每个人都会受益(用户、开发人员——每个人)。
事实上,查看他的代码,我已经有一些关于如何提高 jQuery 速度的想法了!
所以,感谢 Jack,感谢您让我们保持警惕——我们期待着您的库得到改进,每个人都受益。