jQuery遍历是否优于选择器?

And*_*rey 47 javascript performance jquery

使用$("#vacations").find("li").last()是比较好的做法$("#vacations li:last")吗?

背景和我的想法:

我正在玩一个很好的交互式尝试jQuery教程,其中一个任务说:

当您查看代码时,您会注意到其他人正在选择最后一个假期:$("#vacations li:last").你看看这个,你会想,"Traversal会让这种方式变得更快!" 您应该根据这些想法采取行动,重构此代码以使用遍历来查找#vacations中的最后一个li.

我为什么这么认为?对我来说,选择器的使用看起来比遍历要高一些.在我的脑海中,当我指定一个选择器时,由jQuery决定如何更好地获得我需要的单个结果(不需要返回临时结果).

使用复合选择器的额外开销是多少?是因为选择器逻辑的当前实现只是解析字符串并使用遍历API吗?解析一个慢的字符串?未来的实现是否有可能使用它不需要返回中间结果并且比遍历更快的事实?

the*_*tem 21

对此没有任何切割和干燥的答案,但对于:last您正在使用的选择器,它是Selectors API标准的专有扩展.因此,使用本机.querySelectorAll方法无效.

Sizzle所做的基本上是尝试使用你的选择器.querySelectorAll,如果由于选择器无效而抛出异常,它将默认为纯粹的基于JavaScript的DOM选择/过滤.

这意味着包括选择器:last会导致您无法通过本机代码获得DOM选择的速度提升.

此外,还有一些优化,以便当你的选择器非常简单时,就像一个ID或一个元素名称,本机getElementByIdgetElementsByTagName将被使用,这是非常快的; 通常甚至比querySelectorAll.

而且由于该.last()方法只是抓取集合中的最后一项而不是过滤所有项目,这是Sizzle过滤器通常做的事情(至少他们习惯),这也会提升.

IMO,远离专有的东西.现在这.querySelectorAll几乎无处不在,只有使用符合标准的选择器才有真正的优势.在DOM选择后进行任何进一步过滤.


在这种情况下$("#vacations").find("li"),不要担心中期结果.这将使用getElementById随后getElementsByTagName,并将非常快.

如果你真的非常关心速度,减少你对jQuery的使用,并直接使用DOM.


您现在可以在选择器的文档中找到备注,例如:last,它会警告您性能损失:

因为:last是jQuery扩展而不是CSS规范的一部分,使用的查询:last无法利用本机DOM querySelectorAll()方法提供的性能提升.要在使用:last选择元素时获得最佳性能,首先使用纯CSS选择器选择元素,然后使用.filter(":last").

但我不同意这.filter(":last")将是一个很好的替代品.更好的方法是.last()直接定位元素而不是过滤集合.我有一种感觉,他们只是希望人们继续使用他们的非标准兼容选择器.IMO,你最好忘记它们.


Ble*_*der 14

以下是您的设置测试:http://jsperf.com/andrey-s-jquery-traversal

Sizzle,jQuery的选择器引擎,用正则表达式解析字符串,并试图通过使用getElementById和来加速非常基本的选择器getElementsByTagName.如果你的选择是什么,不是更复杂#fooimg,它会尝试使用querySelectorAll,其只接受符合CSS选择器(无:radio,:eq,:checkbox或其他特定jQuery的伪选择).

选择器字符串的可读性速度都较慢,因此实际上没有理由使用它.

通过将选择器字符串分解为Sizzle可以快速解析的简单块(#idtagname),您基本上只是将调用链接到getElementByIdgetElementsByTagName,这可以达到最快速度.