简介
常用的循环遍历语句有for、while、do-while以及for-in,forEach,map。
循环语句
while
前测试循环语句,在循环体内代码被执行前,就会对出口条件求值
do-while
后测试循环语句,常用于循环体中的代码至少要被执行一次
for
是一种前测试循环语句,但它具有在执行循环之前初始化变量和定义循环后要执行的代码的能力
注意点:
1. 在变量的初始化表达式中,也可以不使用 var关键字。
2. 只是把与循环有关的代码集中到一个位置,while 循环做不到的,for循环也做不到
3. 在循环内部定义的变量在外部也可以访问到。如:
var count = 10;
//初始化表达式中,可以不使用 var关键字
for(i = 0 ; i < count ; i++){
alert(i);
}
alert(i); // 10
for-in
for-in一般是用在对象属性名的遍历上的,由于每次迭代操作会同时搜索实例本身的属性以及原型链上的属性,所以效率肯定低下;这个循环很多人爱用,但实际上,经分析测试,在众多的循环遍历方式中,它的效率是最低的
for(var propName in window){
document.write(propName);
}
注意点:
1. 在变量的初始化表达式中,也可以不使用 var关键字。
2. 对象的属性没有顺序,所以通过循环输出的属性名的顺序是不可预测的。每个属性都会被返回一次,但返回的次序因浏览器而异
3. 低版本的浏览器可能会有兼容性的问题。如safari3以前的版本
forEach
数组自带的foreach循环,使用频率较高,是基于函数的迭代,所以实际上性能比普通for循环弱。
myArray.forEach(function (value) {
console.log(value);
});
注意点:
1. 不能中断循环(使用break语句或使用return语句。
2. 需要特别注意的是所有版本的ie都不支持,如果需要可以用JQuery等库
3. 对每个数组项调用外部方法所带来的开销是速度慢的主要原因
变种:
由于foreach是Array型自带的,对于一些非这种类型的,无法直接使用(如NodeList),所以才有了这个变种,使用这个变种可以让类似的数组拥有foreach功能。
Array.prototype.forEach.call(arr,function(el){
});
注意点:
1、实际性能要比普通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++
...
}