浮光掠影(第1季):高性能JavaScript实践

 

在Web2.0和RIA大行其道的今天,JavaScript应用越来越广泛,很多的前端的用户体验效果,都是依赖JS特效来实现。  同时,JS的框架也是百花齐放,老牌的prototype, 最受开发者喜爱的灵巧的jQuery ,新锐JS框架Mootool,得到雅虎力推的YUI,最适合企业应用系统开发的EXTJS等等,一片繁荣景象。

但是,由于用户浏览器使用情况的千差万别,尤其是性能极差的不死的IE6的顽固存在,同时JS的使用已经超越了浏览器的性能极限,而开发者对于JS性能的理解还存在空白,导致JS的性能问题越来越受到人们的重视。下面就我所知道的关于JS性能方面的一些经验总结,欢迎批评指正。

1.避免Javascript加载时Block引起的阻塞

这个问题在所有的JS性能教程上都是很重要的一条了,先呈上一幅图看下阻塞的情况。

JavaScript放于头部引起的阻塞
JavaScript放于头部引起的阻塞

在雅虎的高性能网页开发的14条军规中已经对这样的情况提出了解决方案。

第1条: 尽可能的减少 HTTP 的请求数  => 合并JS,减少Block的次数

第6条: 将脚本移动到底部(包括内联的)=> 减少阻塞对网页加载页面渲染的影响

第10条: 压缩 JavaScript 和 CSS (包括内联的) => 减少阻塞的时间

如果条件允许,使用JS的动态加载技术,也是一个很不错的方案

JavaScript放于尾部,减少阻塞对页面的影响
JavaScript放于尾部,减少阻塞对页面的影响

2.  尽可能的使用局部变量

 
 

 

//错误的代码:html()执行了100次
for (var i=0;i<100;i++){
   $("#id").html(    $("#id").html() + "hello" );
}

//正确的代码:html()执行了2次
var str= $("#id").html() ;
for (var i=0;i<100;i++){
   str =str + "hello";
}
 $("#id").html(str );
 

 

 

下面是测试的性能对比数据

Dom读取100次循环执行的对比数据
Dom读取100次循环执行的对比数据
Dom读取1000次循环执行的对比数据
Dom读取1000次循环执行的对比数据

由上图可以看出,在100次循环的时候,性能对比是1ms VS 30ms, 当1000次循环的时候,性能对比是2ms VS 786 ms ,这个差距是相当惊人的。

对于Dom的操作的资源消耗是非常昂贵, Dom是用来操作,不是用来计算的。用局部变量保存这个值并用来计算,会显著提高JS的性能

3. 多使用ID选择器,少使用CSS选择器

JQ的ID选择器比CSS的选择器要快很多倍,尤其与是页面上的Dom的数量多少成反比,Dom数量越多,CSS选择器越慢

 
 
//性能差的写法
$(".title").html();

//性能好的写法
$("#test").html();
 
JQ CSS选择器 VS ID选择器 性能对比
JQ CSS选择器 VS ID选择器 性能对比

从上图可以看出,1000次循环,id选择器消耗了22ms,而CSS选择器,消耗了139ms,性能相差6倍。

4. 不要轻易获取布局信息

offsetTop,offsetLeft , offsetWidth,offsetHeight,

scrollTop,scrollLeft ,scrollWidth,scrollHeight ,

clientTop,clientLeft,clientWidth,clientHeight

这些都属于布局信息,每调用一次,都会导致页面的布局的重新刷新渲染和布局计算,代价是非常高昂的,在不得不用的时候,只能通过局部变量在存储值,尽量少的去调用。特别是这种计算与定时器相关的时候,重复调用数量明显上升,尤其要注意。

循环获取定位100次2ms VS 1000次21ms
循环获取定位100次2ms VS 1000次21ms

5. 使用冒泡机制减少事件绑定次数

事件绑定也同样是需要消耗资源的,可以利用冒泡和事件拦截机制,在父层绑定一次,对下层的事件进行拦截,减少绑定次数提示性能。

 
 
//不使用冒泡,绑定多次,性能较差
$("ul li").onclick(function(){
  alert(this.html());
});

//使用冒泡,绑定1次,性能较好
$("ul").onclick(function(event){
   alert($(event.target).html());
});
 
绑定父级使用冒泡机制
绑定父级使用冒泡机制

 

上图是有1000个LI的时候的性能对比, 1ms VS 63ms ,差距非常明显。使用冒泡机制还有一个好处,就是在动态新增LI的时候,无需重新事件绑定,同样减少了程序的复杂性

6. 慎用定时器

定时器(timer)是作为监听或者定时执行经常用到的,因为循环定时执行,所以其对网页的性能消耗非常的大,所以,首先要注意控制定时器的间隔时间,不可过于密集,增添客户端的压力,同时也注意尽量使用一个定时器控制多件动作,而不是每个动作一个定时器。

7. 优化效果不明显的那些技巧

在很多优化教程中,还有一些其他的技巧,但是本人测试下来,优化效果是有,但是并不是那么明显.

如: 数组的length应该先预存, if/else  ,  switch/case 应该根据离散概率排序,而不是123顺序排序, 这些优化手段不能说没用,但是收效甚微,不如上面提到的那些手段能起到立杆见影的功效。这就是常说的,20%的努力,可以解决80%的优化问题,但是剩下的20%的优化问题,却需要80%的努力。

8.推荐的性能测试工具FireJSPT

为了做这次测试,我自己写了一个小巧的JS性能测试工具FireJSPT,“工欲善其事,必先利其器”, 已经提交到Google Code 并开源了,有兴趣的童鞋可以去看下。

9.推荐的网站性能优化方面的书

高性能网站建设指南
高性能网站建设指南
高性能网站建设进阶指南:Web开发者性能优化最佳实践
高性能网站建设进阶指南
高性能JavaScript
高性能JavaScript

以上三本书都是网站前端性能优化方面的经典之作,不能不看,推荐下。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值