jQuery选择器性能
根据我表达选择器的方式,我的性能差异很大。 例如,查看这两个选择器,它们选择完全相同的元素:
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(即, jizz嵌入的Sizzle )引入了一种“自下而上”(或“从右到左”)查询DOM的方法。
在你的第二个例子中( "td.someColumnClass span.editMode input"
),Sizzle有效地做到了这一点:
- 获取
someTableRow
所有input
元素 - 对于找到的每个
input
元素,使用class="editMode"
遍历其span
元素的span
元素。 删除没有这些祖先的input
元素 - 对于找到的每个
span.editMode
元素,遍历其祖先树以获取具有class="someColumnClass"
td
元素。 删除没有这些祖先的input
元素
然而,在你的第一个例子中,你通过每次调用find()
,定义一个上下文并从那里向下遍历,明确地限定每一步。 您正在执行“自上而下”的方法。 它相当于在每个步骤传递一个上下文, 通常被认为是一个性能助推器 :
$('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性能的分析博客
关于选择器性能的文章非常有趣: http : //blogs.atlassian.com/developer/2009/08/jquery_bondage.html
在其中,作者显示了一个“绑定”jQuery扩展,它显示了评估函数的次数。