js 性能优化之算法和流程控制


Posted in Javascript onFebruary 15, 2017

循环处理是最常见的编程模式之一,也是提升性能必须关注的要点之一。

常见的优化方案有:

①JavaScript的四种循环(for、do-while、while、for-in)中,for-in循环比其他几种明显要慢。由于每次迭代操作会同时搜索实例或原型属性,for-in循环的每次迭代都会产生更多的开销,所以比其他类型要慢。因此遍历一个属性数量有限的已知属性列表,可以这样优化:

var props = ['prop1', 'prop2'],i = 0;
whlie(i < props.length){
 precess(object[props[i++]]);
}

该代码只关注给定的属性,减少了循环的开销。

而对于,for、while、do-while。我在chrome下测试了一下,先创建一个大小为1000000的数组,每项乘100再叠加。

测试用例:

window.onload = function(){
var items = Array(1000000).join(',').split(',').map(function(item, index) {
 return index;
});
 console.log(forCircle())
 console.log(whileCircle())
 console.log(doCircle())
function forCircle(){
console.profile();
var currTime = new Date();
 var tal = 0;
 for(var i = 0;i < items.length; i++){
  tal = tal + process(items[i]);
 }
 console.profileEnd();
 console.log('forCircle用时:' + (new Date() - currTime) + 'ms');
 return tal;
}
function whileCircle(){
console.profile();
var currTime = new Date();
 var tal = 0;
 var j = 0;
 while (j < items.length){
  tal = tal + process(items[j++]);
 }
 console.profileEnd();
 console.log('whileCircle用时:' + (new Date() - currTime) + 'ms');
 return tal;
}
function doCircle(){
console.profile();
var currTime = new Date();
 var tal = 0;
 var k = 0;
 do{
  tal = tal + process(items[k++]);
 }while (k < items.length)
  console.profileEnd();
 console.log('doCircle用时:' + (new Date() - currTime) + 'ms');
 return tal;
}
function process(item){
 return item*100;
}
}

取某次测试结果:

js 性能优化之算法和流程控制

js 性能优化之算法和流程控制

js 性能优化之算法和流程控制

平均来说,for循环耗时8ms,while耗时4ms,doWhile耗时也是4ms。for是最慢的。

②减少迭代的工作量。把数组长度保存在局部变量中再遍历、颠倒数组的遍历顺序。

最常见的一个循环:

for(var i = 0;i < items.length; i++){
 process(items[i]);
}
//
var j = 0;
while (j < items.length){
 process(items[j++]);
}
//
var k = 0;
do{
 process(items[k++]);
}while (k < items.length)

在这个循环中,每次运行都会产生如下操作:

①查找一次属性(items.length)

②执行数值比较一次(i < items.length) 

③查看控制条件是否为true(i < items.length ==true) 

④一次自增操作(i++)

⑤一次数组查找(items[i])

⑥一次函数调用(process(items[i]))

若把数组长度存到一个局部变量,那么就不需要每次都查找一次items.length,也就提高了性能。

改为这样:

for(var i = 0, len = items.length;i < len; i++){
 process(items[i]);
}
//
var j = 0,
count = items.length;
while (j < count){
 process(items[j++]);
}
//
var k = 0,
num = items.length;
do{
 process(items[k++]);
}while (k < num)

这样在大多数浏览器中能节省大概25%的运行时间(IE中甚至可以节省50%)。总的来说,循环次数大的情况下,运行时间确实有提升。取某次结果如下:

没有局部存量存储数组长度时:

js 性能优化之算法和流程控制

有局部变量存储数组长度时:

js 性能优化之算法和流程控制

③减少迭代次数,“Duffs Device”即“达夫设备“循环体展开技术。适合于迭代次数较大的情况下。

摘抄一下书中达夫设备的基本理念:每次循环中最多可 8 次调用 process()函数。循环迭代次数为元素总数除以8。 因为总数不一定是 8的整数倍, 所以 startAt 变量存放余数, 指出第一次循环中应当执行多少次 process()。比方说现在有 12 个元素,那么第一次循环将调用 process()4次,第二次循环调用 process()8 次,用 2 次循环代替了 12次循环。

基本模式:

var iterations = Math.floor(items.length/8), 
 startAt = items.length%8, 
 i = 0; 
do{ 
 switch(startAt){ 
  case 0 : process(items[i++]); 
  case 7 : process(items[i++]); 
  case 6 : process(items[i++]); 
  case 5 : process(items[i++]); 
  case 4 : process(items[i++]); 
  case 3 : process(items[i++]); 
  case 2 : process(items[i++]); 
  case 1 : process(items[i++]); 
 } 
 startAt = 0; 
 }while(--iterations);

④基于函数的迭代比基于循环的迭代消耗性能更多。例:for循环迭代与forEach函数迭代。 

⑤优化if-else,通常来说,switch比if-else快,但是在判断条件较多时,使用查找表比if-else和switch都快。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木! 

Javascript 相关文章推荐
基于jquery1.4.2的仿flash超炫焦点图播放效果
Apr 20 Javascript
js随机生成网页背景颜色的方法
Feb 26 Javascript
javascript变量声明实例分析
Apr 25 Javascript
JavaScript实现自动变换表格边框颜色
May 08 Javascript
详解JavaScript正则表达式之分组匹配及反向引用
Mar 09 Javascript
JavaScript数组去重由慢到快由繁到简(优化篇)
Aug 26 Javascript
如何解决hover在ie6中的兼容性问题
Dec 15 Javascript
JS实现的ajax和同源策略(实例讲解)
Dec 01 Javascript
微信小程序时间戳转日期的详解
Apr 30 Javascript
JavaScript交换两个变量方法实例
Nov 25 Javascript
浅谈vue获得后台数据无法显示到table上面的坑
Aug 13 Javascript
Angular进行简单单元测试的实现方法实例
Aug 16 Javascript
微信小程序 常用工具类详解及实例
Feb 15 #Javascript
微信小程序 基础知识css样式media标签
Feb 15 #Javascript
js 性能优化之快速响应的用户界面
Feb 15 #Javascript
微信小程序  http请求封装详解及实例代码
Feb 15 #Javascript
DOM事件探秘篇
Feb 15 #Javascript
详解Angularjs 如何自定义Img的ng-load 事件
Feb 15 #Javascript
js实现滑动到页面底部自动加载更多功能
Feb 15 #Javascript
You might like
PHP在字符串中查找指定字符串并删除的代码
2008/10/02 PHP
php 连接mysql连接被重置的解决方法
2011/02/15 PHP
php版微信公众号接口实现发红包的方法
2016/10/14 PHP
PHP中error_reporting函数用法详细介绍
2017/06/11 PHP
yii2多图上传组件的使用教程
2018/05/10 PHP
css把超出的部分显示为省略号的方法兼容火狐
2008/07/23 Javascript
全面理解面向对象的 JavaScript(来自ibm)
2013/11/10 Javascript
js操作模态窗口及父子窗口间相互传值示例
2014/06/09 Javascript
jquery.fastLiveFilter.js实现输入自动过滤的方法
2015/08/11 Javascript
JS简单实现多级Select联动菜单效果代码
2015/09/06 Javascript
Bootstrap modal 多弹窗之叠加显示不出弹窗问题的解决方案
2017/02/23 Javascript
Vue.js学习教程之列表渲染详解
2017/05/17 Javascript
详解jquery选择器的原理
2017/08/01 jQuery
swiper在angularjs中使用循环轮播失效的解决方法
2018/09/27 Javascript
详解angular2.x创建项目入门指令
2018/10/11 Javascript
JS学习笔记之原型链和利用原型实现继承详解
2019/05/29 Javascript
微信小程序tabBar 返回tabBar不刷新页面
2019/07/25 Javascript
解决layui table表单提示数据接口请求异常的问题
2019/09/24 Javascript
JS相册图片抖动放大展示效果的示例代码
2021/01/29 Javascript
[34:10]Secret vs VG 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.24
2019/09/10 DOTA
python之wxPython应用实例
2014/09/28 Python
用Python编写脚本使IE实现代理上网的教程
2015/04/23 Python
python字典基本操作实例分析
2015/07/11 Python
详解Python的Django框架中的Cookie相关处理
2015/07/22 Python
基于Python3.6+splinter实现自动抢火车票
2018/09/25 Python
对python添加模块路径的三种方法总结
2018/10/16 Python
Python面向对象程序设计类变量与成员变量、类方法与成员方法用法分析
2019/04/12 Python
Python接口开发实现步骤详解
2020/04/26 Python
Python使用文件操作实现一个XX信息管理系统的示例
2020/07/02 Python
在CentOS7下安装Python3教程解析
2020/07/09 Python
h5实现获取用户地理定位的实例代码
2017/07/17 HTML / CSS
您在慕尼黑的跑步商店:Lauf-bar
2019/10/11 全球购物
关于爱国的演讲稿
2014/05/07 职场文书
体育馆的标语
2014/06/24 职场文书
安全生产标语大全
2014/10/06 职场文书
经典人生语录分享:不畏将来,不念过去,笑对当下
2019/12/12 职场文书