各类循环遍历对比

简介

经常使用的循环遍历语句有for、while、do-while以及for-in,forEach,map。javascript

循环语句

while

前测试循环语句,在循环体内代码被执行前,就会对出口条件求值css

do-while

后测试循环语句,经常使用于循环体中的代码至少要被执行一次html

for

是一种前测试循环语句,但它具备在执行循环以前初始化变量和定义循环后要执行的代码的能力java

注意点:
1. 在变量的初始化表达式中,也能够不使用 var关键字。
2. 只是把与循环有关的代码集中到一个位置,while 循环作不到的,for循环也作不到
3. 在循环内部定义的变量在外部也能够访问到。如:nginx

var count = 10;

//初始化表达式中,能够不使用 var关键字
for(i = 0 ; i < count ; i++){
    alert(i);
}

alert(i);   // 10

for-in

for-in通常是用在对象属性名的遍历上的,因为每次迭代操做会同时搜索实例自己的属性以及原型链上的属性,因此效率确定低下;这个循环不少人爱用,但实际上,经分析测试,在众多的循环遍历方式中,它的效率是最低的git

for(var propName in window){
    document.write(propName);
}

注意点:
1. 在变量的初始化表达式中,也能够不使用 var关键字。
2. 对象的属性没有顺序,因此经过循环输出的属性名的顺序是不可预测的。每一个属性都会被返回一次,但返回的次序因浏览器而异
3. 低版本的浏览器可能会有兼容性的问题。如safari3之前的版本es6

forEach

数组自带的foreach循环,使用频率较高,是基于函数的迭代,因此实际上性能比普通for循环弱。github

myArray.forEach(function (value) {
  console.log(value);
});

注意点:
1. 不能中断循环(使用break语句或使用return语句。
2. 须要特别注意的是全部版本的ie都不支持,若是须要能够用JQuery等库
3. 对每一个数组项调用外部方法所带来的开销是速度慢的主要缘由web

变种:
因为foreach是Array型自带的,对于一些非这种类型的,没法直接使用(如NodeList),因此才有了这个变种,使用这个变种可让相似的数组拥有foreach功能。canvas

Array.prototype.forEach.call(arr,function(el){  
   
});

注意点:
一、实际性能要比普通foreach弱

map

这种方式也是用的比较普遍的,虽然用起来比较优雅,但实际效率还比不上foreach

arr.map(function(n){  
   
});

for-of(须要es6支持)

这种方式是es6里面用到的,性能要好于forin,但仍然比不上普通for循环

for(let value of arr) {  
   
});

性能对比

性能优化

1. 优化变量声明

JS不一样与其余面向对象的语言,他没有块及做用域,有的仅仅是函数做用域,因此当使用了一个变量,而后不久在函数中又从新声明的话,就可能产生逻辑错误。对于JavaScript,只要你的变量是在同一个做用域中(同一函数),它都被当作是声明的,即便是它在var声明前使用的时候。合理的写法即把变量声明在函数的开始,而不是在循环内部才开始定义变量。

//优化JS的变量定义,变量定义在开始位置,避免产生块级做用域的误区
    var i;
    for(i=0; i<values.length; i++){
        ...
    }

2. 优化循环中动态集合读取
NodeList 、NameNodeMap 和 HTMLCollection,这三个集合每当文档结构发生变化时,它们都会获得更新(并且仍是动态的更新)。下面代码中的divs 所引用的就是NodeList 对象

//致使NodeList无限循环的循环书写方式
    var divs = document.getElementsByTagName("div");
    for(var i=0; i<divs.length; i++){
        var div =document.createElement("div");
        document.body.appendChild(div);
        alert("Infinite loop");
    }

上述代码每次循环都要对divs.length 求值,循环代码会致使一个严重的问题,每次循环都要对divs.length 求值。

如下是优化后的代码:

//避免NodeList无限循环的循环书写方式
var divs = document.getElementsByTagName("div");
//先将length用变量储存起来
 for(var i=0, len = divs.length ; i<len; i++){
        var div =document.createElement("div");
        document.body.appendChild(div);
        alert("Infinite loop will not happen");
    }

3. 用i+=1 代替i++
从《Javascript语言精粹》里面看来的,大体意思是说用了i++ 会有潜在的安全问题,i+=1 比起i++ 更加“原生”能够提高性能,可是我的认为可读性下降,根据须要各自取舍吧。

4. 减值迭代优化循环
从最大值开始,在循环中不断减值的迭代器更加高效(只高效了一点点)。若是值的处理顺序可有可无,那么循环能够改成i 减值,可是下降可读性,

//减值迭代优化循环
    for(var i=values.length-1; i>=0; i--){
    ...
    }

循环优化大串联

  • 性能最优化的写法
//循环优化大串联
    var i;  //优化变量声明
    var divs = document.getElementsByTagName("div");
    for(i=divs.length-1; i>=0; i-=1){  
    //优化循环中动态集合读取、减值迭代、用i-=1 代替 i--
    ...
    }
  • 以优化性能的前提下兼顾可读性
//合理的循环优化
    var i,len;  //优化变量声明
    var divs = document.getElementsByTagName("div");
    for(i=0, len = divs.length; i<len; i++){  
    //优化循环中动态集合读取,必要时也能够用i+=1 代替 i++
    ...
    }

参考资料

  1. 性能比较工具
  2. JS几种数组遍历方式以及性能分析对比
  3. 高性能JavaScript 循环语句和流程控制
  4. Javascript的循环优化探究
相关文章
相关标签/搜索