优化jQuery选择器的最佳方法是什么?

时间:2012-12-22 15:04:38

标签: javascript jquery html jquery-selectors

我在JSP中多次使用这个jQuery选择器:

 $("#customers tbody tr td input[type='checkbox'][name='selectedCustomers']")

我在一些博客上找到的解决方案是我应该先做:

var customer=$('#customers')

然后使用上述客户对象进行进一步调用。

 customer.find("tbody tr td input[type='checkbox'][name='selectedCustomers']")

我的问题是,这个解决方案会有所不同吗?为什么?

我的理解

当我这样做时

$("#customers tbody tr td input[type='checkbox'][name='selectedCustomers']")

jQuery内部将首先获取与div id="customers"关联的对象 (通过document.getElementById(“customers”))然后将遍历指定的 checkbox。如果我按照建议的解决方案,那么document.getElementById("customers")将只被触发一次,其余的将是相同的。因此,我将自己从不必要的多个document.getElementById中拯救出来,但其余的将是相同的。我的理解是否正确?如果是的话,仅仅是为了我所知,document.getElementById是一项成本更高的手术吗?

修改: -

我不是仅仅在上述选择器上方多次使用,而是在div id =“customer”下使用其他可能的选择器。所以,如果我首先缓存客户对象并且如果我不这样做,那么问题是性能方面的差异是什么?

4 个答案:

答案 0 :(得分:6)

你无法做到那一点。我猜最多,这是:

$('#customers td [name="selectedCustomers"]')

......应该提高性能。接下来,如果你每次都在查询selectedCustomers,你应该缓存整个事情:

var selectedCustomers = $('#customers td [name="selectedCustomers"]');

否则,如果名称是动态的,并且每页只有一个名称相同的项目......

var item = $(document.getElementsByName(someName)[0]);
另一方面,

缓存$('#customers')几乎毫无意义。 .find customers上的querySelector将首先完成与整个选择器相同的工作,尤其是{{1}}支持。

答案 1 :(得分:3)

您似乎错过了缓存对象的基本点。缓存对象后,将对存储对象执行该选择器中的任何进一步遍历或操作,并且不需要搜索DOM以首先定位选择器并在每次需要使用它时创建集合< / p>

每次调用$("#customers tbody tr td input[type='checkbox'][name='selectedCustomers']")时,必须执行文档搜索以创建元素集合,然后才能对集合进行任何更改。

缓存集合意味着无需进一步搜索,从而提高性能

/* locate and store the collection once*/
var $checkboxes=$("#customers tbody input[name='selectedCustomers']");
/* look within previously stored collection*/
$checkboxes.filter(/* expression*/ ).doSomething();

使用document.getElementById将比jQuery搜索更快,因为它不需要jQuery库进行的附加函数调用。但是,如果您希望将结果用作jQuery对象,例如: $( document.getElementById('foo'))  单一用于缓存对象的收益可能不值得担心

答案 2 :(得分:1)

  

所以我将自己从不必要的多重document.getElementById中拯救出来,但其余的将是相同的。

是。但也许也没有,因为选择器是从右到左进行评估的(参见this articlethis SO question)。假设一个高效的引擎,如果你只选择文档树的一部分进行评估,如果你先选择#customers然后再选择.find(),那么它的工作就会减少。但我对此并不是100%肯定。

  

document.getElementById操作成本更高吗?

不,这很便宜。 Ids是标识单个元素的标准属性,浏览器将为它构建非常高性能的查找表 - 您可以假设它几乎为O(1)

  

customer.find("tbody tr td input[type='checkbox'][name='selectedCustomers']")

另一方面,需要评估DOM树的DOM选择器查询成本非常高,特别是如果在JS代码(jQuery sizzle)中手动完成而不是本机 - 虽然这个相当简单的查询被委派给本地querySelectorAll

我猜测#customers是你的表元素。因此,对于性能,省略tbody tr td标记,它们是强制性的(假设您没有使用它们明确排除<thead> / <tfoot><th>元素的复选框)。无论如何,你都不会找到<input>作为表元素的直接子元素 - 并且选择器引擎要做的事情要少得多。

此外,如果您很好地了解了标记并且可以假设只有复选框具有name属性,那么您也可以省略标记名和类型属性选择器。这意味着您可以委托给本地getElementsByName,这可以再次提升性能:

$(document.getElementById("customers").getElementsByName("selectedCustomers"))

如果您需要检查元素是否为复选框,您仍然可以过滤它们。有了这个,你最终可能会

$(customer.get(0).getElementsByName("selectedCustomers")).filter(":checkbox")

但是,为了证明性能提升,您只能进行测试,测试,测试;你需要在实际的整页上做到这一点。

答案 3 :(得分:0)

http://jsperf.com/different-jquery-selector-tests

查看这个小测试。基本上 $(&#39; #div&#39;)。find(&#39;#p&#39;); 是最快的 $(&#39; div&#39; ;)。找到(&#39;#p&#39;); 是最慢的。