jQuery选择器性能
-
05-07-2019 - |
题
我的性能差异很大,这取决于我如何表达我的选择器。例如,查看这两个选择器,它们选择完全相同的元素:
A) someTableRow.find("td.someColumnClass").find("span.editMode").find("input")
B) someTableRow.find("td.someColumnClass span.editMode input")
我希望B)更快,因为只有1次调用,但实际上我发现A)的执行速度提高了大约8倍。我不知道为什么,任何人都有任何见解?感谢
解决方案
假设您至少使用jQuery 1.3(即添加了Sizzle),您所看到的性能是由于DOM遍历的变化。从这里:
直到并包含jQuery 1.2.6 选择器引擎以“自上而下”的方式工作。 (或“从左到右”)方式。 jQuery的 1.3.x(即jQuery嵌入的 Sizzle )引入了“自下而上” ; (要么 “从右到左”的查询方法 DOM。
在你的第二个例子中(" td.someColumnClass span.editMode input"
),Sizzle有效地做到了这一点:
- 获取
someTableRow
内的所有 - 找到每个
input
元素,使用class =" editMode"
遍历其span
元素的祖先树。删除没有这些祖先的input
元素 - 找到每个
span.editMode
元素,使用class =" someColumnClass"
遍历td
元素的祖先树。删除没有这些祖先的input
元素
醇>
输入
元素
然而,在您的第一个示例中,您通过每次调用 find()
显式限定每个步骤,定义上下文并从那里遍历 down 。您正在执行“自上而下”的操作。做法。它相当于在每一步传递一个上下文,这是通常被视为性能助推器:
$('input', $('span.editMode', $('td.someColumnClass', someTableRow)))
其他提示
因为您正在减少搜索的上下文。
在案例B中,它必须搜索每个DOM元素以查看它是否符合标准。
在情况A中,可以快速决定忽略不是“td.someColumnClass”的任何内容,那么它可以采用DOM的该子集并忽略不在“span.editMode”中的任何内容。因此,它具有更小的元素集来搜索以现在找到“输入”。
A是更多的电话,但更简单。 B是一个电话,但更复杂。在这种情况下,通话的复杂性大大超过了呼叫的数量。
根据我的经验,JQuery处理selctors的方式与CSS略有不同。
Josh指出,减少搜索的上下文是关键。
我发现使用两个参数选择器非常快
这如何比较速度?
你不需要这里的所有变种只是为了弄清楚我在做什么。
var columnClasses = $('.someColumnClass');
var tableCell = $('td', columnclasses);
var editMode = $('.editmode', tableCell);
var spanInside = $('span', editMode);
var inputFinally = $('input', spanInside);
善,
丹
我自己做了一些关于jQuery Selector Performance的研究。一个很大的问题是Internet Explorer上的classname查找。 IE不支持getElementsByClassName - 因此jQuery和其他框架“重新实现”它通过遍历所有DOM元素在JavaScript中完成。 查看以下有关 jQuery Selector Performance <的分析博客/ A>
这里有一篇关于选择器性能的非常有趣的文章: http:// blogs .atlassian.com /显影剂/ 2009/08 / jquery_bondage.html
在其中,作者显示了“绑定”。 jQuery扩展,显示函数被评估的次数。