提高jQuery性能的十个诀窍


Posted in Javascript onNovember 14, 2013

1. 使用最新版本的jQuery

jQuery的版本更新很快,你应该总是使用最新的版本。因为新版本会改进性能,还有很多新功能。

下面就来看看,不同版本的jQuery性能差异有多大。这里是三条最常见的jQuery选择语句:

$(‘.elem')

$(‘.elem', context)

context.find(‘.elem')

我们用1.4.2、1.4.4、1.6.2三个版本的jQuery测试,看看浏览器在1秒内能够执行多少次。结果如下:
提高jQuery性能的十个诀窍

可以看到,1.6.2版本的运行次数,远远超过两个老版本。尤其是第一条语句,性能有数倍的提高。

其他语句的测试,比如.attr(“value”)和.val(),也是新版本的jQuery表现好于老版本。

2. 用对选择器

在jQuery中,你可以用多种选择器,选择同一个网页元素。每种选择器的性能是不一样的,你应该了解它们的性能差异。

(1)最快的选择器:id选择器和元素标签选择器

举例来说,下面的语句性能最佳:

$(‘#id')

$(‘form')

$(‘input')

遇到这些选择器的时候,jQuery内部会自动调用浏览器的原生方法(比如getElementById()),所以它们的执行速度快。

(2)较慢的选择器:class选择器

$(‘.className')的性能,取决于不同的浏览器。

Firefox、Safari、Chrome、Opera浏览器,都有原生方法getElementByClassName(),所以速度并不慢。但是,IE5-IE8都没有部署这个方法,所以这个选择器在IE中会相当慢。

(3)最慢的选择器:伪类选择器和属性选择器

先来看例子。找出网页中所有的隐藏元素,就要用到伪类选择器:

$(‘:hidden')

属性选择器的例子则是:

$(‘[attribute=value]‘)

这两种语句是最慢的,因为浏览器没有针对它们的原生方法。但是,一些浏览器的新版本,增加了querySelector()和querySelectorAll()方法,因此会使这类选择器的性能有大幅提高。

最后是不同选择器的性能比较图。

提高jQuery性能的十个诀窍

可以看到,ID选择器遥遥领先,然后是标签选择器,第三是Class选择器,其他选择器都非常慢。

3. 理解子元素和父元素的关系

下面六个选择器,都是从父元素中选择子元素。你知道哪个速度最快,哪个速度最慢吗?

$(‘.child', $parent)

$parent.find(‘.child')

$parent.children(‘.child')

$(‘#parent > .child')

$(‘#parent .child')

$(‘.child', $(‘#parent'))

我们一句句来看。

(1) $(‘.child', $parent)

这条语句的意思是,给定一个DOM对象,然后从中选择一个子元素。jQuery会自动把这条语句转成$.parent.find(‘child'),这会导致一定的性能损失。它比最快的形式慢了5%-10%。

(2) $parent.find(‘.child')

这条是最快的语句。.find()方法会调用浏览器的原生方法(getElementById,getElementByName,getElementByTagName等等),所以速度较快。

(3) $parent.children(‘.child')

这条语句在jQuery内部,会使用$.sibling()和javascript的nextSibling()方法,一个个遍历节点。它比最快的形式大约慢50%。

(4) $(‘#parent > .child')

jQuery内部使用Sizzle引擎,处理各种选择器。Sizzle引擎的选择顺序是从右到左,所以这条语句是先选.child,然后再一个个过滤出父元素#parent,这导致它比最快的形式大约慢70%。

(5) $(‘#parent .child')

这条语句与上一条是同样的情况。但是,上一条只选择直接的子元素,这一条可以于选择多级子元素,所以它的速度更慢,大概比最快的形式慢了77%。

(6) $(‘.child', $(‘#parent'))

jQuery内部会将这条语句转成$(‘#parent').find(‘.child'),比最快的形式慢了23%。

所以,最佳选择是$parent.find(‘.child')。而且,由于$parent往往在前面的操作已经生成,jQuery会进行缓存,所以进一步加快了执行速度。

具体的例子和比较结果,请看这里。

4. 不要过度使用jQuery

jQuery速度再快,也无法与原生的javascript方法相比。所以有原生方法可以使用的场合,尽量避免使用jQuery。

请看下面的例子,为a元素绑定一个处理点击事件的函数:

$(‘a').click(function(){

alert($(this).attr(‘id'));

});

这段代码的意思是,点击a元素后,弹出该元素的id属性。为了获取这个属性,必须连续两次调用jQuery,第一次是$(this),第二次是attr(‘id')。

事实上,这种处理完全不必要。更正确的写法是,直接采用javascript原生方法,调用this.id:

$(‘a').click(function(){

alert(this.id);

});

根据测试,this.id的速度比$(this).attr(‘id')快了20多倍。

5. 做好缓存

选中某一个网页元素,是开销很大的步骤。所以,使用选择器的次数应该越少越好,并且尽可能缓存选中的结果,便于以后反复使用。

比如,下面这样的写法就是糟糕的写法:

jQuery(‘#top').find(‘p.classA');

jQuery(‘#top').find(‘p.classB');

更好的写法是:

var cached = jQuery(‘#top');

cached.find(‘p.classA');

cached.find(‘p.classB');

根据测试,缓存比不缓存,快了2-3倍。

6. 使用链式写法

jQuery的一大特点,就是允许使用链式写法。

$(‘div').find(‘h3′).eq(2).html(‘Hello');

采用链式写法时,jQuery自动缓存每一步的结果,因此比非链式写法要快。根据测试,链式写法比(不使用缓存的)非链式写法,大约快了25%。

7. 事件的委托处理(Event Delegation)

javascript的事件模型,采用”冒泡”模式,也就是说,子元素的事件会逐级向上”冒泡”,成为父元素的事件。

利用这一点,可以大大简化事件的绑定。比如,有一个表格(table元素),里面有100个格子(td元素),现在要求在每个格子上面绑定一个点击事件(click),请问是否需要将下面的命令执行100次?

$(“td”).bind(“click”, function(){

$(this).toggleClass(“click”);

});

回答是不需要,我们只要把这个事件绑定在table元素上面就可以了,因为td元素发生点击事件之后,这个事件会”冒泡”到父元素table上面,从而被监听到。

因此,这个事件只需要在父元素绑定1次即可,而不需要在子元素上绑定100次,从而大大提高性能。这就叫事件的”委托处理”,也就是子元素”委托”父元素处理这个事件。

具体的写法有两种。第一种是采用.delegate()方法:

$(“table”).delegate(“td”, “click”, function(){

$(this).toggleClass(“click”);

});

第二种是采用.live()方法:

$(“table”).each(function(){

$(“td”, this).live(“click”, function(){

$(this).toggleClass(“click”);
});
});

这两种写法基本等价。唯一的区别在于,.delegate()是当事件冒泡到指定的父元素时触发,.live()则是当事件冒泡到文档的根元素后触发,因此.delegate()比.live()稍快一点。此外,这两种方法相比传统的.bind()方法还有一个好处,那就是对动态插入的元素也有效,.bind()只对已经存在的DOM元素有效,对动态插入的元素无效。

根据测试,委托处理比不委托处理,快了几十倍。在委托处理的情况下,.delegate()又比.live()大约快26%。

8. 少改动DOM结构

(1)改动DOM结构开销很大,因此不要频繁使用.append()、.insertBefore()和.insetAfter()这样的方法。

如果要插入多个元素,就先把它们合并,然后再一次性插入。根据测试,合并插入比不合并插入,快了将近10倍。

(2)如果你要对一个DOM元素进行大量处理,应该先用.detach()方法,把这个元素从DOM中取出来,处理完毕以后,再重新插回文档。根据测试,使用.detach()方法比不使用时,快了60%。

(3)如果你要在DOM元素上储存数据,不要写成下面这样:

var elem = $(‘#elem');

elem.data(key,value);

而要写成:

var elem = $(‘#elem');

$.data(elem,key,value);

根据测试,后一种写法要比前一种写法,快了将近10倍。因为elem.data()方法是定义在jQuery函数的prototype对象上面的,而$.data()方法是定义jQuery函数上面的,调用的时候不从复杂的jQuery对象上调用,所以速度快得多。(此处可以参阅下面第10点。)

9. 正确处理循环

循环总是一种比较耗时的操作,如果可以使用复杂的选择器直接选中元素,就不要使用循环,去一个个辨认元素。

javascript原生循环方法for和while,要比jQuery的.each()方法快,应该优先使用原生方法。

10. 尽量少生成jQuery对象

每当你使用一次选择器(比如$(‘#id')),就会生成一个jQuery对象。jQuery对象是一个很庞大的对象,带有很多属性和方法,会占用不少资源。所以,尽量少生成jQuery对象。

举例来说,许多jQuery方法都有两个版本,一个是供jQuery对象使用的版本,另一个是供jQuery函数使用的版本。下面两个例子,都是取出一个元素的文本,使用的都是text()方法。你既可以使用针对jQuery对象的版本:

var $text = $(“#text”);

var $ts = $text.text();

也可以使用针对jQuery函数的版本:

var $text = $(“#text”);

var $ts = $.text($text);

由于后一种针对jQuery函数的版本不通过jQuery对象操作,所以相对开销较小,速度比较快。

Javascript 相关文章推荐
jquery 插件 任意位置浮动固定层
Dec 25 Javascript
JavaScript 调试器简介
Feb 21 Javascript
Mootools 1.2 手风琴(Accordion)教程
Sep 15 Javascript
JavaScript的单例模式 (singleton in Javascript)
Jun 11 Javascript
Javascript下IE与Firefox下的差异兼容写法总结
Jun 18 Javascript
div模拟滚动条效果示例代码
Oct 16 Javascript
js支持键盘控制的左右切换立体式图片轮播效果代码分享
Aug 26 Javascript
JS中append字符串包含onclick无效传递参数失败的解决方案
Dec 26 Javascript
AngularJS遍历获取数组元素的方法示例
Nov 11 Javascript
Node.js开发之套接字(socket)编程入门示例
Nov 05 Javascript
Vue 组件的挂载与父子组件的传值实例
Sep 02 Javascript
vue使用video插件vue-video-player的示例
Oct 03 Javascript
优化Jquery,提升网页加载速度
Nov 14 #Javascript
Jquery AJAX POST与GET之间的区别
Nov 14 #Javascript
Jquery中$.get(),$.post(),$.ajax(),$.getJSON()的用法总结
Nov 14 #Javascript
JS正则表达式大全(整理详细且实用)
Nov 14 #Javascript
JS中typeof与instanceof之间的区别总结
Nov 14 #Javascript
jQuery探测位置的提示弹窗(toolTip box)详细解析
Nov 14 #Javascript
使用jQuery解决IE与FireFox下createElement方法的差异
Nov 14 #Javascript
You might like
聊天室php&mysql(二)
2006/10/09 PHP
php知道与问问的采集插件代码
2010/10/12 PHP
php抽奖小程序的实现代码
2013/06/18 PHP
基于命令行执行带参数的php脚本并取得参数的方法
2016/01/25 PHP
PHP自定义函数获取URL中一级域名的方法
2016/08/23 PHP
tp5.1 框架数据库高级查询技巧实例总结
2020/05/25 PHP
两个数组去重的JS代码
2013/12/04 Javascript
javascript图片相似度算法实现 js实现直方图和向量算法
2014/01/14 Javascript
IE浏览器中图片onload事件无效的解决方法
2014/04/29 Javascript
JS小游戏之极速快跑源码详解
2014/09/25 Javascript
js Calender控件使用详解
2015/01/05 Javascript
javascript中Object使用详解
2015/01/26 Javascript
基于jQuery实现的QQ表情插件
2015/08/25 Javascript
莱鸟介绍window.print()方法
2016/01/06 Javascript
angular+ionic 的app上拉加载更新数据实现方法
2017/01/16 Javascript
JS去掉字符串末尾的标点符号及删除最后一个字符的方法
2017/10/24 Javascript
改变vue请求过来的数据中的某一项值的方法(详解)
2018/03/08 Javascript
vue构建动态表单的方法示例
2018/09/22 Javascript
js面向对象之实现淘宝放大镜
2020/01/15 Javascript
python虚拟环境 virtualenv的简单使用
2020/01/21 Javascript
Javascript实现html转pdf高清版(提高分辨率)
2020/02/19 Javascript
详解Vue 数据更新了但页面没有更新的 7 种情况汇总及延伸总结
2020/05/28 Javascript
[01:30]2016国际邀请赛中国区预选赛神秘商店火爆开启
2016/06/26 DOTA
用python处理MS Word的实例讲解
2018/05/08 Python
把csv文件转化为数组及数组的切片方法
2018/07/04 Python
解决django 新增加用户信息出现错误的问题
2019/07/28 Python
Python安装whl文件过程图解
2020/02/18 Python
Python判断字符串是否为空和null方法实例
2020/04/26 Python
Belvilla法国:休闲度假房屋出租
2020/10/03 全球购物
旅游管理本科生求职信
2013/10/14 职场文书
秋季运动会表扬稿
2014/01/16 职场文书
单位绩效考核方案
2014/05/11 职场文书
公司授权委托书范本
2014/09/18 职场文书
房屋授权无偿使用证明
2014/11/29 职场文书
2015年物业公司保洁工作总结
2015/10/22 职场文书
python turtle绘图命令及案例
2021/11/23 Python