我正在编写一个 jQuery 插件,现在处于优化阶段。
我想知道哪种方式通常能够使脚本更快,并且有哪些重要的缓解因素:
- 在开始时生成大量类和 ID,使在后面查找 dom 元素更容易(也更快?)。
- 尽量减少类和 ID(不创建它们可以节省时间),但是随后以更复杂的方式查找元素(例如,对象中的第 n 项),我认为这比获取 id/class 更慢。
我正在编写一个 jQuery 插件,现在处于优化阶段。
我想知道哪种方式通常能够使脚本更快,并且有哪些重要的缓解因素:
浏览器的工作方式是,在加载时创建一个内存中的DOM树,其形式如下:
P
_______________|______________
| |
childNodes attributes
______________|___________ |
| | | title = 'Test paragraph'
'Sample of text ' DIV 'in your document'
|
childNodes
__________|_______
| | |
'HTML you might' B 'have'
如果你查找的是 P > DIV > B
,那么这个查找过程需要先找到所有的 P
元素,然后在这些 P
元素中查找所有的 DIV
元素,最后再在这些 DIV
元素中查找所有的 B
元素。嵌套层次越深,需要进行的查找就越多。此外,它可能会查找所有的 P > DIV
,只发现没有任何一个匹配元素拥有 B
,从而浪费时间。
通过 ID 进行查找更快,因为 ID 是唯一的,所以 DOM 可以将它们存储为哈希表条目,这样就可以非常快速地进行查找。就 jQuery 而言,实现可能略有不同,但是 document.getElementById 具有最快的查找时间,因此 $('#my_node_id')
也应该很快。
因此,如果你的节点没有 ID,你可以找到最近的具有 ID 的祖先节点,并相对于该祖先节点查找你的节点。
#my_node_id > div > b
因为查找只需要在 #my_node_id
子树下发生,所以它比 p > div > b
更快。
这个问题不是非常具体,所以我无法直接给出与您的代码直接相关的建议,但以下是一些我最喜爱的jQuery优化技巧:
#container
div内,则执行$(something, '#container');
.myclass
速度较慢。在没有支持getElementsByClassName
的浏览器中,内部会遍历每个单独的元素以查看它是否具有您正在搜索的类。如果您知道类只会应用于特定元素,则使用tag.myclass
速度更快,因为jQuery可以使用本地getElementsByTagName
并仅在其中搜索。$('#myform input:eq(2)');
或类似的操作,但我更喜欢执行$('input','#myform').eq(2);
来帮助jQuery。myDiv
并且你假设它是child
的最后一个兄弟节点:<div>parent
<div>child</div>
<div>myDiv</div>
</div>
<div>parent
<div>child</div>
<div>myDiv</div>
<div>child</div>
</div>
如果你的代码依赖于对结构的假设,那么它会变得非常脆弱。给节点添加类和id将防止出现这种情况。
我认为你应该选择第一种方法。同时请记住,通过类获取节点总是比通过id获取节点慢。
我尽可能地减少插件引入文档的钩子数量。所谓“钩子”,指的是ID或类。
完全避免它们的最佳方法是在插件闭包内保留对任何创建元素的引用。例如:
jQuery.fn.addList = function(items, fn){
var $list = $('<ul/>').html('<li>' + items.join('</li><li>') + '</li>');
return this.each(function(){
$(this).append($list);
fn.call($list);
});
};
$('body').addList(['item 1', 'item 2'], function(){
var referenceToTheList = this;
console.log(referenceToTheList, '<- this is my list, no hooks involved!');
});