3

引言

平时工作中循环的使用场景可以说是非常之多了,昨天改别人代码时候有位同事非常喜欢用ES6等新特性,一个数组的遍历全部都是用for...of...,然后业务需求要用到数组中的序号index值,就很尴尬了,我只能改回forEach了。但是for...of...在很多情况下还是很强大的,比如中断之类的。下面就总结下js中常见的几种循环方法。

常见的循环方法

for loop

说起for循环,大家的思绪应该马上就回到第一次上计算机课时候的美好大一生活吧,几乎所有语言通用的循环方法:

for (var i = 0; i < 10; i++) {
  console.log(i);
}
for (let i = 0; i < products.length; i++) {
  console.log(products[i]);
}

简单易懂,如果你不知道es5和es6的循环方法, 就用这个来对数组进行遍历,并且可以用break中断。但是对数组进行循环包一层这个条件总归有些啰嗦,有没有更简洁的方法呢?当然,继续往下看。

forEach

forEach是Array.prototype上的方法,我们可以使用它对数组进行循环遍历。因此一个数组就可以直接如下调用此方法即可:

products.forEach(function(product) {
  console.log(product);
});

你不需要先去计算数组的总数才能循环,直接用就可以了。那么如果需要获取每项的序号呢?forEach方法第二个参数就是当前循环项的index值。

products.forEach(function(product,index) {
  console.log(index, product);
});

也就等价于for循环中的写法:
for (var i = 0; i < products.length; i++) {
console.log(i, products[i]);
}

唯一美中不足的就是forEach不支持中断循环,如果不需要条件中断循环数组的话,采用forEach是最好的选择,尤其是遍历一些嵌套数组双重循环时候,写起来代码可读性会好很多。

for...in...

var arr = [
  'a', 
  'b'
];
for (var i in arr) {
  console.log(i); //0 1
}

以任意顺序遍历一个对象的可枚举属性。大家不要忘了数组也是对象...我们经常用这个方法来遍历一个普通对象,其实也是可以迭代一个数组的,数组的索引就是0,1,2这样的数字。但是强烈建议不要这样用。因为循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性。
MDN上也明确提示:for...in不应该用于迭代一个 Array,其中索引顺序很重要。
并且如果你为了过滤迭代继承的属性方法,又要用hasOwnProperty这些方法,非常繁琐。
总之通常情况下我们不会去要迭代继承而来的属性,因此不太推荐使用for...in...
甚至你用forEach这样做都好一点:

Object.keys(obj).forEach(function(key) { console.log(obj[key]) });

for...of...

最后出场也是ES6最新支持的迭代方法就是for...of...。MDN上的定义:
在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。
可以看到它支持的种类非常多,最常用的就是Arrayarguments了,但是注意虽然支持这么多并不能像for...in...用于普通Object的迭代。上面我们不推荐for...in...应用于数组,那么for...of...就非常合适了:

var arr = [
  'a', 
  'b'
];
for (var i of arr) {
  console.log(i); //a b
}

遍历数组,每项直接就是值,并且可以中断,如果不关心索引的话,强烈推荐。但是回到引言那里如果你需要索引值这就不是很方便了。但是ES6中有新的entries方法可以让for...in...也可以获取索引。

for (let [index, val] of arr.entries()) {
      console.log(index);   
}

总结

  1. 当遍历Array时候,在需要索引时候推荐用forEach,不需要索引时候用for...of...
  2. 当迭代Object时候,虽然只能用for...in...配合hasOwnproperty过滤不需要的,但我还是推荐用Object.keys()配合forEach

    Object.keys(obj).forEach(function(key) { ... });
  3. 当迭代Stringarguments等可迭代对象时候,也只能使用for...of...

参考


Alee
291 声望8 粉丝

既然路走偏了,那就重新开始吧。