我在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”下使用其他可能的选择器。所以,如果我首先缓存客户对象并且如果我不这样做,那么问题是性能方面的差异是什么?
答案 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 article或this SO question)。假设一个高效的引擎,如果你只选择文档树的一部分进行评估,如果你先选择#customers
然后再选择.find()
,那么它的工作就会减少。但我对此并不是100%肯定。
不,这很便宜。 Ids是标识单个元素的标准属性,浏览器将为它构建非常高性能的查找表 - 您可以假设它几乎为
document.getElementById
操作成本更高吗?
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;); 是最慢的。