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 相关文章推荐
JS中完美兼容各大浏览器的scrolltop方法
Apr 17 Javascript
JavaScript学习总结之JS、AJAX应用
Jan 29 Javascript
原生JS实现旋转木马式图片轮播插件
Apr 25 Javascript
JavaScript 数组中最大最小值
Jun 05 Javascript
Javascript获取图片原始宽度和高度的方法详解
Sep 20 Javascript
jQuery实现标签页效果实战(4)
Feb 08 Javascript
jQuery实现鼠标移到某个对象时弹出显示层功能
Aug 23 jQuery
layui实现下拉复选功能的例子(包括数据的回显与上传)
Sep 24 Javascript
使用Webpack 搭建 Vue3 开发环境过程详解
Jul 28 Javascript
JavaScript实现简单验证码
Aug 24 Javascript
原生JS实现相邻月份日历
Oct 13 Javascript
Ant design vue table 单击行选中 勾选checkbox教程
Oct 24 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 截取字符串函数整理(支持gb2312和utf-8)
2010/02/16 PHP
PHP导出EXCEL快速开发指南--PHPEXCEL的使用详解
2013/06/03 PHP
thinkphp实现上一篇与下一篇的方法
2014/12/08 PHP
PHP实现二叉树的深度优先与广度优先遍历方法
2015/09/28 PHP
laravel 操作数据库常用函数的返回值方法
2019/10/11 PHP
JS等比例缩小图片尺寸的实例
2013/02/27 Javascript
JS调用CS里的带参方法实例
2013/08/01 Javascript
jquery动态添加option示例
2013/12/30 Javascript
Vue.js实现无限加载与分页功能开发
2016/11/03 Javascript
js实现手机拍照上传功能
2017/01/17 Javascript
纯js三维数组实现三级联动效果
2017/02/07 Javascript
详解数组Array.sort()排序的方法
2020/05/09 Javascript
Vue的MVVM实现方法
2017/08/16 Javascript
JS对象序列化成json数据和json数据转化为JS对象的代码
2017/08/23 Javascript
Postman模拟发送带token的请求方法
2018/03/31 Javascript
vue实现添加与删除图书功能
2018/10/07 Javascript
layer.alert自定义关闭回调事件的方法
2019/09/27 Javascript
js+css实现全屏侧边栏
2020/06/16 Javascript
Python获取运行目录与当前脚本目录的方法
2015/06/01 Python
详解python调度框架APScheduler使用
2017/03/28 Python
python实现发送邮件功能
2017/07/22 Python
使用 Python 实现微信公众号粉丝迁移流程
2018/01/03 Python
Python wxPython库消息对话框MessageDialog用法示例
2018/09/03 Python
Python Web框架之Django框架Form组件用法详解
2019/08/16 Python
python统计函数库scipy.stats的用法解析
2020/02/25 Python
浅谈python元素如何去重,去重后如何保持原来元素的顺序不变
2020/02/28 Python
基于Python的OCR实现示例
2020/04/03 Python
HTML5+CSS3实例 :canvas 模拟实现电子彩票刮刮乐代码
2016/12/30 HTML / CSS
教你如何一步一步用Canvas写一个贪吃蛇
2018/10/22 HTML / CSS
详解Html5原生拖拽操作
2018/01/12 HTML / CSS
德国滑雪和户外用品网上商店:XSPO
2019/10/30 全球购物
公司道歉信范文
2014/01/09 职场文书
创先争优活动承诺书
2014/08/30 职场文书
2014个人年终工作总结范文
2014/12/15 职场文书
惊涛骇浪观后感
2015/06/05 职场文书
Go语言安装并操作redis的go-redis库
2022/04/14 Golang