2012-12-22 42 views
15

我使用这个jQuery选择在我的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( “客户”)),然后将运行至指定 checkbox。如果我去了建议的解决方案,然后document.getElementById("customers")将只触发一次,其余的将是相同的。所以,我从不需要多个document.getElementById保存自己,但其余的将是相同的。我的理解是否正确?如果是的,只是我的知识的缘故,是一个document.getElementById更昂贵的操作?

编辑: -

我不是只用上面说的选择多次,而且其他可能的选择DIV ID =“客户”下。因此,如果我首先缓存客户对象,并且如果我不这样做,那么问题又是什么在性能方面有所不同?

+4

如果匹配的元素不会改变,你应该缓存整个选择器不仅是#客户,所有的问题都是不支持的选择器,但这是浏览器的依赖 – Alexander

+0

我不认为这是存在的除了第二种方式以外,没有任何区别更适合阅读。 – SaidbakR

+2

@sємsєм缓存甚至父母肯定会提高性能。更多的搜索包含在那个对象中,而不是完整的DOM – charlietfl

回答

6

没有办法,你需要的是具体的。我猜,最多的是:

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

......这应该会提高性能。接下来,如果你每次实际上查询selectedCustomers,你应该缓存整个事情:

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

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

var item = $(document.getElementsByName(someName)[0]); 

缓存仅仅是$('#customers'),另一方面,几乎没有意义。 .findcustomers会做同样多的工作,摆在首位的整体选择,尤其是querySelector支持。

+0

你说过“缓存$('#customers'),另一方面,几乎没有意义。找到客户将做的工作和整个选择器一样多第一个地方,特别是使用querySelector支持“。这是否意味着如果我做了$(“#customers'tbody tr td input [type ='checkbox'] second time,DOM will not be traversed to locate the div id =”customers“?if yes,jquery second times will get the对象与div id =“customer”相关联,它会在内部缓存吗? –

+0

@MSach:我说它将会被第二次遍历,只要你用选择器调用jQuery,将会是一个查询,但是如果你缓存了一些更具体的东西,那么性能差异可能会很重要(请参阅上面注释中的jsPerf) – Ryan

+0

感谢minitech,让我通过询问我真正想要的:)来澄清我的疑问。如果我做$(“#customers someSelector”),Dom遍历只会在jquery开始寻找不是针对#customers的选择器(因为它是一个id,并且可以直接从浏览器准备的table/Map中获得),所以不需要为了遍历dom的id)对吧?这是iam试图问的东西,如果回答是肯定的,那么我同意你是否 我缓存与id相关联的对象,它的一种毫无意义,因为它将在任何情况下都是O(1)操作 –

3

你似乎缺少缓存对象的基本点。一旦对象被缓存,该选择中的任何进一步的遍历或操控存储的对象上进行,不需要搜索的DOM首先定位选择和创建集合每次你需要使用它

时间

每当您致电$("#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库做addiitonal函数调用。但是,如果你想使用结果作为一个jQuery对象,如: $(document.getElementById('foo')) 的收益很可能不值得担心单次使用缓存的对象

+0

你的意思是如果我第二次做$(“#customers tbody tr td input [type ='checkbox']',DOM DOM必须被遍历到第一个找到div id =”customers“的对吗?另一方面,如果我做在第一次缓存与div#客户关联的对象后,该遍历将被保存。是否正确? –

1

所以我从不需要多个document.getElementById但其余节约自己将是一样的。

是的。但也可能不是,因为选择器是从右到左评估的(请参阅this articlethis SO question)。假设一个高效的引擎,如果它只在文档树的一部分上进行评估,那么如果首先选择#customers,然后选择其中的.find(),那么它的工作量就会减少。但我不是100%确定的。

document.getElementById更昂贵的操作?

不,它很便宜。 ID是识别单个元素的标准属性,浏览器将为其构建非常高性能的查找表 - 您可以假定它接近O(1)

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

在另一方面,这需要评估DOM树DOM选择查询是非常昂贵的,尤其是手工完成的JS代码(jQuery的嘶嘶声),而不是本机 - 尽管这相当简单查询委托给原生querySelectorAll

我猜测#customers是你的表格元素。所以对于性能,省略tbody tr td标签,它们是强制性的(假设您没有使用它们明确排除<thead>/<tfoot><th>元素中的复选框)。无论如何,你不会发现一个<input>作为表元素的直接子元素,而选择器引擎的功能更少。另外,如果你知道你的标记并且可以假设只有复选框有name属性,那么你也可以省略标记名和类型属性选择器。这意味着你可以委托给本地getElementsByName,应再次提高性能一点点:

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

如果您需要检查的元素是复选框,你仍然可以进行过滤。因此,您可能会以

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

但是,为了证明性能增益,您只能测试,测试,测试;你需要在你的实际完整页面上做到这一点。

+0

谢谢Bergi。让我清楚我的疑问,问我实际上想要什么:)。这是它。如果我做$(“ #客户someSelector“),Dom遍历只会启动一次jquery开始寻找选择器不是为 #客户(作为它的ID和可以直接从表/地图准备通过浏览器获得,所以不需要遍历DOM的ID)。对吗? –

+0

会对你有所帮助,如果你可以点亮上面的评论 –

+0

是的,你的评论是正确的。 – Bergi

相关问题