很久之前就发现使用forEach循环数组时是无法跳出循环的,break和return都不生效。数组中的所有元素都会被遍历。今天花时间研究了一下深层的原理。有不对的地方欢迎指正。
1.举个例子
var list = [0,1,2,3,4,5,6,7,8,9];
list.forEach(function(item){
console.log(item);
if (item > 3 ){
return;
}
});
输出结果是0,1,2,3,4,5,6,7,8,9。并没有在大于3的时候终止循环。
如果把return替换为break会报错:Uncaught SyntaxError: Illegal break statement
2.forEach使用说明
arr.forEach(function callback(currentValue, index, array) {
//your iterator
}[, thisArg]);
currentValue --- 当前处理的元素
index --- 当前处理元素的索引
array ---forEach应用的数组
有一段提示写到了在forEach中break和return的用法。原文如下:
There is no way to stop or break a forEach()loop other than by throwing an exception. If you need such behavior, theforEach()method is the wrong tool. Use a plain loop instead. If you are testing the array elements for a predicate and need a Boolean return value, you can use
every()
or
some()
instead. If available, the new methodsfind()
orfindIndex()
can be used for early termination upon true predicates as well.
意思就是说在forEach中使用break和return是错误的,如果希望使用break或者return请使用every或者some函数。
3.为什么不能使用return和break
在V8的源码里找了又找也没有找到forEach函数的源码,从其他实现的forEach中也能发现一些端倪。
Array.prototype.myEach = function(callback) {
for (var i = 0; i < this.length; i++)
callback(this[i], i, this);
};
猜测js的实现源码应该也是这种原理,我们传入的function是这里的回调函数。在回调函数里面使用break肯定是非法的,因为break只能用于跳出循环,而我们的回调函数不是循环体。
在回调函数中使用return,只是将结果返回到上级函数,也就是这个for循环中,并没有结束for循环,所以return也是无效的。
举个例子实际说明一下:
var subFunction = function(callback){
for (var i = 0;i < 10; i++){
callback(i);
console.log(i);
}
}
var func = function(i){
if(i>3){
return
}else{
console.log('callback i =' + i);
}
}
subFunction(func);
我们在forEach中使用return就如同func中的return一样,只是在回调函数中执行了return,并不能影响到上级函数中的for循环,自然不会中断for循环的运行了。
4.for vs forEach
需要遍历数组的时候使用哪个好呢?
forEach的优点是写法简单,避免了下标溢出的情况。
for的优点是性能比forEach好,可以使用break和return。
大家根据实际情况择优使用吧。
如有理解不正确的地方,欢迎指正~~