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 相关文章推荐
拖动table标题实现改变td的大小(css+js代码)
Apr 16 Javascript
Javascript基础知识(一)核心基础语法与事件模型
Sep 29 Javascript
Bootstrap每天必学之模态框(Modal)插件
Apr 26 Javascript
Node.js的基本知识简单汇总
Sep 19 Javascript
利用jquery给指定的table动态添加一行、删除一行的方法
Oct 12 Javascript
BootStrap实现手机端轮播图左右滑动事件
Oct 13 Javascript
jquery实现左右滑动式轮播图
Mar 02 Javascript
利用babel将es6语法转es5的简单示例
Dec 01 Javascript
vue安装和使用scss及sass与scss的区别详解
Oct 15 Javascript
vue mounted 调用两次的完美解决办法
Oct 29 Javascript
layui实现鼠标移动到单元格上显示数据的方法
Sep 11 Javascript
JavaScript实现单点登录的示例
Sep 23 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中使用smarty生成静态文件的例子
2014/04/24 PHP
php实现随机生成易于记忆的密码
2015/06/19 PHP
Zend Framework教程之Zend_Config_Ini用法分析
2016/03/23 PHP
php提交过来的数据生成为txt文件
2016/04/28 PHP
PHP封装的mysqli数据库操作类示例
2019/02/16 PHP
thinkPHP和onethink微信支付插件分享
2019/08/11 PHP
js刷新框架子页面的七种方法代码
2008/11/20 Javascript
基于jquery的图片懒加载js
2010/06/30 Javascript
分享一道笔试题[有n个直线最多可以把一个平面分成多少个部分]
2012/10/12 Javascript
jQuery语法高亮插件支持各种程序源代码语法着色加亮
2013/04/27 Javascript
JS实现浏览器状态栏文字闪烁效果的方法
2015/10/27 Javascript
JavaScript性能优化之小知识总结
2015/11/20 Javascript
Bootstrap每天必学之媒体对象
2015/11/30 Javascript
基于Javascript实现倒计时功能
2016/02/22 Javascript
一种Javascript解释ajax返回的json的好方法(推荐)
2016/06/02 Javascript
微信小程序前端源码逻辑和工作流
2016/09/25 Javascript
JavaScript表单验证完美代码
2017/03/02 Javascript
ionic App问题总结系列之ionic点击系统返回键退出App
2017/08/19 Javascript
JavaScript高级函数应用之分时函数实例分析
2018/08/03 Javascript
element-ui 关于获取select 的label值方法
2018/08/24 Javascript
在vue项目中正确使用iconfont的方法
2018/09/28 Javascript
JavaScript深入V8引擎以及编写优化代码的5个技巧
2019/06/24 Javascript
vue 封装 Adminlte3组件的实现
2020/03/18 Javascript
详解vue中v-model和v-bind绑定数据的异同
2020/08/10 Javascript
vue项目中openlayers绘制行政区划
2020/12/24 Vue.js
Python 旋转打印各种矩形的方法
2019/07/09 Python
python3.6 tkinter实现屏保小程序
2019/07/30 Python
python定义类的简单用法
2020/07/24 Python
python利用递归方法实现求集合的幂集
2020/09/07 Python
HTML5+lufylegend实现游戏中的卷轴
2016/02/29 HTML / CSS
波兰购物网站:MALL.PL
2019/05/01 全球购物
在职党员进社区活动总结
2014/07/05 职场文书
2015年发展党员工作总结报告
2015/03/31 职场文书
搞笑婚庆主持词
2015/06/29 职场文书
导游词之日本富士山
2020/01/06 职场文书
蓝牙耳机怎么连接电脑win11? Win11蓝牙耳机连接电脑的技巧
2023/01/09 数码科技