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 相关文章推荐
JQuery入门——用one()方法绑定事件处理函数(仅触发一次)
Feb 05 Javascript
解析JSON对象与字符串之间的相互转换
Dec 18 Javascript
js实现按Ctrl+Enter发送效果
Sep 18 Javascript
Javascript代码实现仿实例化类
Apr 03 Javascript
jquery.gridrotator实现响应式图片展示画廊效果
Jun 23 Javascript
jquery实现左右滑动菜单效果代码
Aug 27 Javascript
JavaScript tab选项卡插件实例代码
Feb 23 Javascript
JS实现回到页面顶部动画效果的简单实例
May 24 Javascript
JS实现页面打印功能
Mar 16 Javascript
web前端vue之CSS过渡效果示例
Jan 10 Javascript
实例讲解v-if和v-show的区别
Jan 31 Javascript
Vue函数式组件-你值得拥有
May 09 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双引号中访问数组元素报错的解决方法
2018/02/01 PHP
PHP基于cookie实现统计在线人数功能示例
2019/01/16 PHP
理解JavaScript变量作用域更轻松
2009/10/25 Javascript
Jquery cookie操作代码
2010/03/14 Javascript
关于Jqzoom的使用心得 jquery放大镜效果插件
2010/04/12 Javascript
javascript基础之查找元素的详细介绍(访问节点)
2013/07/05 Javascript
如何在父窗口中得知window.open()出的子窗口关闭事件
2013/10/15 Javascript
设为首页和收藏的Javascript代码(亲测兼容IE,Firefox,chrome等浏览器)
2013/11/18 Javascript
js实现类似菜单风格的TAB选项卡效果代码
2015/08/28 Javascript
跟我学习javascript的作用域与作用域链
2015/11/19 Javascript
js+canvas简单绘制圆圈的方法
2016/01/28 Javascript
jquery ajax后台返回list,前台用jquery遍历list的实现
2016/10/30 Javascript
使用JavaScript判断用户输入的是否为正整数(两种方法)
2017/02/05 Javascript
JS全角与半角转化实例(分享)
2017/07/04 Javascript
JavaScript使用prototype原型实现的封装继承多态示例
2018/08/31 Javascript
微信小程序http连接访问解决方案的示例
2018/11/05 Javascript
详解Node.js 中使用 ECDSA 签名遇到的坑
2018/11/26 Javascript
Vue实现表格批量审核功能实例代码
2019/05/28 Javascript
详解JavaScript中分解数字的三种方法
2021/01/05 Javascript
python的几种开发工具介绍
2007/03/07 Python
Python中元组,列表,字典的区别
2017/05/21 Python
解决pycharm安装后代码区不能编辑的问题
2018/10/28 Python
用Python逐行分析文件方法
2019/01/28 Python
Python 继承,重写,super()调用父类方法操作示例
2019/09/29 Python
python运用sklearn实现KNN分类算法
2019/10/16 Python
python实现按关键字筛选日志文件
2019/12/24 Python
基于Python和PyYAML读取yaml配置文件数据
2020/01/13 Python
Python任务调度利器之APScheduler详解
2020/04/02 Python
CSS3 实用技巧:实现黑白图像效果示例代码
2013/07/11 HTML / CSS
canvas绘制圆角头像的实现方法
2019/01/17 HTML / CSS
提高EJB性能都有哪些技巧
2012/03/25 面试题
爱国口号
2014/06/19 职场文书
因个人原因离职的辞职信范文
2015/05/12 职场文书
2015小学毕业班工作总结
2015/07/21 职场文书
利用html+css实现菜单栏缓慢下拉效果的示例代码
2021/03/30 HTML / CSS
pytorch实现ResNet结构的实例代码
2021/05/17 Python