您的位置: 首页 > 技术文档 > 网页制作 > 提升JavaScript运行速度之循环篇
浏览器根据什么来判定脚本失控? 回到列表 JavaScript中尽量用局部变量的原因
 提升JavaScript运行速度之循环篇

作者:明达 时间: 2009-02-20 文档类型:翻译 来自:七月佑安

根据Nicholas的说法,有四种代码会拖慢脚本的运行,并最终导致脚本失控。分别是次数过多的同步循环、庞大的函数体、不恰当的递归和不合理的DOM调用。这篇着重讲第一个原因。最后给出了一个开发模式,替换传统的循环结构,可以完全避免脚本失控的状况发生。

原文标题:Speed up your JavaScript, Part 1
原文作者:Nicholas C. Zakas

在我 上一篇帖子译文)中,谈到了各个浏览器究竟会在什么情况下弹出脚本失控提示,对于Internet Explorer来说,当浏览器执行了数量过多的语句时就会停止执行脚本,而其他的浏览器,则是持续执行脚本超过一定时间的时候就会给出提示。而我们要探讨的核心问题,不是这些浏览器如果探测失控的脚本,而是我们如何才可以让脚本运行的更快一些,从而避免这些警告。

脚本失控基本上有以下四个方面的原因:

  1. 在循环中执行了太多的操作。
  2. 臃肿的函数体
  3. 过多的递归
  4. 过多的DOM调用

在这篇帖子中,我将会把重点放到第一条上:循环中的过多操作。循环的操作是同步进行的,所以执行一个循环所花费的时间完全取决于循环的次数。因此有两种情况会导致循环执行的时间过长,并直接导致锁定浏览器。一是循环体中包含了太多的操作,二是循环的次数过多。这两种情况都能直接导致锁定浏览器,并显示脚本失控的提示。

解决这个问题的诀窍就是用下面这两个问题来评估每个循环:

  1. 这个循环必须要同步执行么?
  2. 循环里面的数据,必须要按顺序执行么?

如果两个问题的答案都是否定的话,你就可以选择将循环里的操作进行分解。关键是要根据代码的具体环境确定上面两个问题的答案。一个典型的循环可能像下面这个样子:

for(var i=0; i < items.length; i++){
   process(items[i]);
}

乍一看这个循环并没有太大的问题,是不是会运行很长时间完全取决于循环的次数。如果紧接循环后没有其他代码在执行的时候需要依赖于循环的结果,那么对于第一个问题的答案就是“不”。你还可以发现,循环每次只处理一个数值,而且不依赖于上一次循环的结果,所以对于第二个问题的答案同样也是否定的。这就意味着,循环可以通过某种方式进行拆解,不会导致锁定浏览器而显示脚本失控的提示。

在《Professional JavaScript, Second Edition》这本书中,对于那些执行次数非常巨大的虚幻,我推荐使用下面的方式来处理:

function chunk(array, process, context){
   setTimeout(function(){
       var item = array.shift();
       process.call(context, item);

       if (array.length > 0){
           setTimeout(arguments.callee, 100);
       }
   }, 100);
}

chunk()函数的用途就是将一个数组分成小块处理(这也是名字的由来),我们可以传递三个参数。要处理的数组对象、处理函数以及一个可选的上下文变量,用于设置process()函数中对应的this对象。第一个timer用于处理操作之间的延时(这里设置为100毫秒,大家可以根据实际需要自行修改)。每次执行这个函数,都会将数组中的第一个对象取出,并传给process()函数进行操作,如果这时process()中还有未处理完的对象,另外一个timer就会启动,用于重复等待。上面提到的循环,可以通过下面的方法使用这个函数:

chunk(items, process);

需要注意的是,在这里数组采用了队列(queue)的形式,而且在循环的过程中,每次都会发生修改。如果你要修改数组的原始状态,这里介绍两种途径:一种是通过concat()函数,在传递之前,建立一个当前数组的副本:

chunk(items.concat(), process);

另外一种选择是直接修改chunk()函数,直接在函数内部进行修改:

function chunk(array, process, context){
   var items = array.concat();   //clone the array
   setTimeout(function(){
       var item = items.shift();
       process.call(context, item);

       if (items.length > 0){
           setTimeout(arguments.callee, 100);
       }
   }, 100);
}

注意这种方法要比只保存一个索引安全的多,因为数组的内容在下次计时器生效之前可能会发生变化。

这里提到的chunk()函数,只是优化循环性能的一个起点。你可以根据需要不断改进它,让它拥有更多的功能。比如说,在数组中所有对象都处理完成以后,可以增加一个函数回调。无论你是否会按照这种方式对函数进行修改,这只是一种JavaScript的代码开发模式,可以帮助优化数组的处理性能,还可以避免那个脚本失控的警告。

本文链接:http://www.blueidea.com/tech/web/2009/6434.asp 

出处:七月佑安
责任编辑:bluehearts

◎进入论坛网页制作WEB标准化版块参加讨论,我还想发表评论

相关文章 更多相关链接
JavaScript中尽量用局部变量的原因
JavaScript的2008
JavaScript Tween算法及缓动效果
仿Apple滑动条(拖动)产品展示效果
如何走出JavaScript初学困境
作者文章
浏览器根据什么来判定脚本失控?
JavaScript中尽量用局部变量的原因
JavaScript的2008
热门搜索:CSS Fireworks 设计比赛 网页制作 web标准 用户体验 UE photoshop Dreamweaver Studio8 Flash 手绘 CG
站点最新 站点最新列表
悟道web标准:前端性能优化
纯中文域名".中国"今日提交申请
世界之窗3.0皮肤设计大赛结果公布
使用jQuery制作滑动动画效果的层
如何设计网页横幅
Plump 图标设计
Subrat Nayak图标设计
百度知道推出文档分享服务
CSS Sprites(CSS雪碧):要还是不要?
UIRSS三周年纪念日推出V2公测版
栏目最新 栏目最新列表
Firefox的Jetpack扩展案例分析
阿里妈妈UED谈CSS Sprites技术
Photoshop中设计绿色时尚Web网站
操作Dom节点实现间歇滚动新闻
浏览器15年历史回顾
如何创建Firefox的Jetpack扩展
全透视:CSS Z-index 属性
用PS 3D工具绘制甜麦圈包装袋
悟道Web标准:让W3C标准兼容终端
悟道WEB标准:统一思想,遵循标准

蓝色理想版权申明:除部分特别声明不要转载,或者授权我站独家播发的文章外,大家可以自由转载我站点的原创文章,但原作者和来自我站的链接必须保留(非我站原创的,按照原来自一节,自行链接)。文章版权归我站和作者共有。

转载要求:转载之图片、文件,链接请不要盗链到本站,且不准打上各自站点的水印,亦不能抹去我站点水印。

特别注意:本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有,文章若有侵犯作者版权,请与我们联系,我们将立即删除修改。

本文暂时没有评论和评分

您的评论
用户名:  口令:
说明:输入正确的用户名和密码才能参与评论。如果您不是本站会员,你可以注册 为本站会员。
注意:文章中的链接、内容等需要修改的错误,请用报告错误,以利文档及时修改。
不评分 1 2 3 4 5
注意:请不要在评论中含与内容无关的广告链接,违者封ID
请您注意:
·不良评论请用报告管理员,以利管理员及时删除。
·尊重网上道德,遵守中华人民共和国的各项有关法律法规
·承担一切因您的行为而直接或间接导致的民事或刑事法律责任
·本站评论管理人员有权保留或删除其管辖评论中的任意内容
·您在本站发表的作品,本站有权在网站内转载或引用
·参与本评论即表明您已经阅读并接受上述条款
推荐文档 | 打印文档 | 评论文档 | 报告错误  
专业书推荐 更多内容
《Web标准设计》
闪魂-FlashCS4完美入门与案例精粹
Waver_h's华丽世界
Illustrator CS3质感绘画表现技法
《Flash短片轻松学》
《用户体验要素》
《JavaScript语言精粹》
作品集 更多内容

一条鱼 2010-2月作品 酷熊体验馆 公寓类地产站 贝克洛门窗 Kids and Science 双生子日记星座卡 房地产教学案例