在JavaScript或者几乎所有的编程语言中,for循环语句都是处理循环的主要手段,其使用方式相信大家都很熟悉。在处理循环时,我们还可以使用break
、continue
来控制循环的结束或者跳过本次处理。但ES5中引入的forEach
作为处理循环的利器能否沿袭for循环的特点呢?答案是否定的,forEach
有着自己独特的特性:break、continue不能在forEach中使用
var arr = [1, 2, 3, 4];
arr.forEach(function(item) {
console.log(item);
if (item > 2) {
break;
}
});
var arr = [1, 2, 3, 4];
arr.forEach(function(item) {
if (item === 2) {
continue;
}
console.log(item);
});
上面两段代码乍看起来应该像是对的,但是运行时会抛出异常。那我们该如何实现类似的功能呢?
return模拟continue
这里其实有个乍看起来奇特的场景:return
语句不能结束forEach
。很奇怪吧,即使在switch...case
中使用return
语句也可以结束一个代码块:
function getColor(color) {
switch(color) {
case 'red':
return '#ff0000';
case 'blue':
return '#00ff00';
default:
return null;
}
console.log('不可知之地'); // A
}
console.log(getColor('red')); // #ff0000
return
的作用是用来结束一个代码块的,上面的行A是不会被执行到的。那再来看下return
在forEach
中的表现:
var arr = [1, 2, 3, 4];
arr.forEach(function(item) {
console.log(item);
if (item > 2) {
return;
}
});
我们的本意是只打印出1和2,但是实际上结果却是将数据中所有的数据都打印出来了,这是因为我们传入forEach
的是一个函数,每次循环都会执行此函数(传入参数不同),而函数中的return
只会结束当前函数,所以上面的return
没有任何意义,但是我们可以利用此特性起到continue
语句的作用:
var arr = [1, 2, 3, 4];
arr.forEach(function(item) {
if (item > 2) {
return;
}
console.log(item);
});
// 1 2
无法在forEach中模拟break
上面的例子只是调换一下代码位置即可实现只打印出3之前的数据的功能,但是这种实现并不优雅,因为对于2以后的元素来说仍然还要进行非必要的函数调用(假设arr是有序数组),这种方案只适用于跳过特定某些数据的场景:
var arr = [1, 2, 3, 4];
arr.forEach(function(item) {
// 针对跳过某些数据时可以使用return模拟continue
if (item === 2) {
return;
}
console.log(item);
});
// 1 3 4
但是对于只打印出3之前的数据的功能来说,使用for循环实现无疑是最好的方案(可以搭配break
使用):
var arr = [1, 2, 3, 4];
for (var i=0, len=arr.length; i<len; i++) {
if (arr[i] > 2) {
break;
}
console.log(arr[i]);
}
// 1 2
我们是无法在
forEach
中模拟break
的,因为术业有专攻,如果想要此功能请大胆的使用for循环。
更多
上文中提到的for循环既包括普通的for循环,其实也包括ES6中的for...of
循环(continue
、break
能够正常使用)。ES5和ES6之后好多人感觉使用普通的for循环逼格比较低,但是使用普通的for循环并无任何不妥之处,而且对于大数据量来说普通的for循环性能上更具优势。