1. 尽量使用id选择元素
当使用id选择元素时,jQuery调用浏览器的document.getElementById()进行选择元素,而使用class进行选择元素时,由于DOM本身不支持通过class进行选择元素,所以jQuery不得不遍历真个Dom文档来判断每个元素是否包含要选择的class,我使用firebug的console时间记录分析,在我电脑上id大概比class快10倍,如果页面内容很多,快的就越多,测试代码如下:
console.time('class'); for (var i = 0; i < 10000; i++) $(".content"); console.timeEnd('class'); console.time('id'); for (var i = 0; i < 10000; i++) $("#header"); console.timeEnd('id');
元素选择器的性能比class快一些,而比id要慢一些,因为当用元素进行选择时可以调用document.getElementsByTagName(),所以优先id,元素次之,class最差。
2.当必须用元素或class选择器时,尽量使用离它最近的祖先节点的id作为前缀
例如 $(“.content”)和$(“#left .content”),前者需要遍历整个DOM文档,而$(“#left .content”)则可以先调用document.getElementById(“#left”),这一步的开销可以忽略,然后在#left元素的后代里进行遍历,#left 和.content离得越近,需要遍历的元素就越少,所以使用祖先里id作为前缀可以获得一定的性能提升,取决整个文档结构。
3.当必须用元素或class选择器时,尽量把该元素的元素标签作为前缀
在第一条里说过,元素选择器要比class选择器快,所以$(“div.content”)要比$(“.content”)快一些,在我电脑上测试结果是大概快15%左右,当然也可以把第二条和第三条结合起来一起使用。
4. 查询时使用上下文(context)来减少查询次数
JQuery查询时有一个可选参数context, 即$(express, [context]), context可以是dom元素,元素集和JQuery对象。Context的作用是设定查询的范围,默认是document,所以$(“a”)等同于$(“a”, document), 我们可以通过给定context值来减少查询范围,例如我只想在<div id=”#header”>…</div>里进行查找a标签,就可以使用$(“a”, document.getElementById(“#header”)), 记住,第二个参数context一定要是一个DOM对象才能提高性能,如果是$(“a”,”#header”),虽然可以用,但不会提升性能,因为JQuery会自动把它转换成$(“#header”).find(“a”);
这一条和第二条以及第三条相似,都是通过限定查询范围来减少查询次数,尤其是dom结构比较复杂的页面,效果更是明显。
5.缓存查询结果,减少查询次数 通过元素或class进行查询时非常消耗性能的,因此应该尽量减少查询次数,例如:
for (var i = 0; i < 1000; i++) { $(".content").append(i); }
上面的代码需要对同一个元素进行1000次查询,浪费了大量时间,可以查询的结果保存下来以供后面使用来减少查询次数,var content = $(“.content”);
for (var i = 0; i < 1000; i++) { content.append(i); }
6. 通过链式操作减少查询次数以及代码量
通常jQuery的函数调用会返回上一次查询的元素,例如我们要设置元素的宽度和高度,通常我们会分别调用函数来完成,$(“.content”).width(100);
$(“.content”).height(100);width()和height()函数的返回值都是$(“.content”),因此$(“.content”).width(100).height(100)来减少一次查询,当然我们可以写得非常长,例如:
$(“.content”).width(100).height(100).show().fadeIn().addClass(‘abc’);
7.尽量减少直接进行DOM操作
直接操作DOM是比较慢的,因此如果频繁的操作DOM会带来很大的性能问题,典型的例子是向DOM里插入元素,例如,我们要向body结尾插入1000个p元素,
第一种方法:
8.尽量减少事件代理
大量的事件代理会带来很大的性能问题,例如我们要给100个列表元素添加事件,就是100个事件代理,如果元素更多,性能会更差,我们可以利用事件的冒泡特性来减少代理,具体就是我们把事件代理放在这个100个列表元素的父节点
ul元素上,当事件发生时会传递(冒泡)到他们的父节点上,然后再判断是哪个元素发生了点击行为,代码如下:
$('ul#myList).bind('click', function(e){ var target = e.target, // e.target grabs the node that triggered the event. $target = $(target); // wraps the node in a jQuery object if (target.nodeName === 'LI') { $target.addClass('clicked'); // do stuff } });
JQuery1.4.2引入了.delegate()函数,可以更方便的处理事件代理,代码如下:
$(“ul#myList”).delegate(“li”, “click”, function() {$(this).addClass(‘clicked’);});
delegate()函数不仅可以方便的处理事件代理,还可以起到类似.live()函数的作用,即对于后面加入的元素也起作用。
9.使用data()来保存数据
平常大家有临时数据要保存时通常是保存在class中或自定义一个属性来保存,例如<div class=”123″></div>或者<div count=”3″></div>,其实这些方式使用起来不太方便,同时也给HTML添加了大量无意义的数据,同时基本上也只能存储字符串,JQuery内置了.data()函数来存储数据,可以任意类型的数据,包括对象,
$("#abc").data('count', 3);//存数据 var count = $("#abc").data('count')//读数据 $("#abc").removeData('count');//删除数据
这种方法使用方便,而且不会对HTML结构带来影响,非常简洁
10.尽量减少不必要代码执行数量
所谓不必要的代码主要是指在当前页面根本不需要执行的代码,这些代码可能是其它页面需要的,这种情况非常常见,尤其是只有一个js文件时,所有页面的代码在每个页面都会执行一遍。最理想的情况是每个页面只执行每个页面各自的代码,但这会带来严重的代码组织维护问题。例如:
$("#a").click(function() {...});//page a需要执行的代码 $("#b").click(function() {...});//page b需要执行的代码 $("#c").click(function() {...});//page c需要执行的代码
page a载入时会把上面的代码都执行一遍,很明显后面两行代码不应该执行的,虽然JQuery对于查询失败时处理得比较好,但是查询成功和查询失败花的时间是差不多,只是失败后就不会执行后续的操作,因此我们可以通过判断某个元素是否存在来决定是否执行该代码,
if ($("#a").length > 0) {....} //只有是page a才执行 if ($("#b").length > 0) {....} //只有是page b才执行 if ($("#c").length > 0) {....} //只有是page c才执行
以上这种方式对于有非常多代码的文件来说特别有效,可以减少大量不必要的查询,要知道通过class进行查询是特别消耗时间的,当然了,对于大的网站来说可以把不同页面的代码放到不同的文件里,然后知载入需要的js文件。
11.使用良好的命名方式来区分jQuery对象和普通的JavaScript对象
在使用JQuery开发时一般会把原生的js代码和JQuery代码混合在一起使用,但这两种对象有本质的区别,因此最好通过良好的命名方式来避免把两种对象变量搞混了,现在公认的一种比较好的方式是使用$作为JQuery变量的开头,
var $jquery = $("#abc"); //JQuery对象变量 var jquery = $jquery[0]; //原生js变量
这样就避免一些很明显的错误。