ES6 Array系列(三) Array中的forEach方法可以用break、continue跳出循环?

飄風不終朝,驟雨不終日。——《道德經》

简介


Array.prototype上有很多方法,比较常用的就是everyfilterforEachmapsome这些循环方法,可以通过breakcomtinue跳出循环?
现在基本上都是通过forEachevery来代替for循环,for循环可以通过breakcontinue跳出循环。而 forEach 可以不可以呢,下面一步一步的验证一下。

for


for中遇到break就会退出当前循环,后面的循环不会再执行。代码如下

1
2
3
4
5
6
7
8
9
let arr = [1, 2, 3, 4, 5];
let str = '';
for (let item of arr) {
if (item === 2) {
break;
}
str += item + '-';
}
console.log(str); // 1-

for中遇到continue就会退出当前本次循环,后面的循环会执行。代码如下

1
2
3
4
5
6
7
8
9
let arr = [1, 2, 3, 4, 5];
let str = '';
for (let item of arr) {
if (item === 2) {
continue;
}
str += item + '-';
}
console.log(str); // 1-3-4-5-

for中不能使用 return,不然会报错

forEach、every、some、filter、map


如果想退出forEach,就只能通过return, 它会退出当前本次循环,后面的循环会执行。代码如下

1
2
3
4
5
6
7
8
9
var arr = [1, 2, 3, 4, 5];
var str = '';
arr.forEach((item) => {
if (item === 2) {
return;
}
str += item + '-';
});
console.log(str); // 1-3-4-5-

如果想退出every,就只能通过return, 它会退出当前循环,后面的循环不会再执行。代码如下

1
2
3
4
5
6
7
8
9
var arr = [1, 2, 3, 4, 5];
var str = '';
arr.every((item) => {
if (item === 2) {
return;
}
str += item + '-';
});
console.log(str); // 1-

如果想退出some,就只能通过return, return falsereturn true它的表现是不一致的。return false它的表现和forEach中的表现一致。 代码如下

1
2
3
4
5
6
7
8
9
10
var arr = [1, 2, 3, 4, 5];
var str = '';
arr.forEach((item) => {
if (item === 2) {
return;
// return false;
}
str += item + '-';
});
console.log(str); // 1-3-4-5-

return trueevery表现一致,代码如下:

1
2
3
4
5
6
7
8
9
var arr = [1, 2, 3, 4, 5];
var str = '';
arr.forEach((item) => {
if (item === 2) {
return true;
}
str += item + '-';
});
console.log(str); // 1-

如果想退出filter,就只能通过return, 它会退出当前本次循环,后面的循环会执行。代码如下

1
2
3
4
5
6
7
8
9
var arr = [1, 2, 3, 4, 5];
var str = '';
arr.filter((item) => {
if (item === 2) {
return;
}
str += item + '-';
});
console.log(str); // 1-3-4-5-

如果想退出map,就只能通过return, 它会退出当前本次循环,后面的循环会执行。代码如下

1
2
3
4
5
6
7
8
9
var arr = [1, 2, 3, 4, 5];
var str = '';
arr.map((item) => {
if (item === 2) {
return;
}
str += item + '-';
});
console.log(str); // 1-3-4-5-

forEacheverysome中不能用breakcontinue跳出循环,不然会报错。

都知道filtermap会返回一个新的数组,而everysome会返回一个Boolean类型的。

some 和 every 需要注意的地方


some() 方法测试是否至少有一个元素可以通过被提供的函数方法。该方法返回一个 Boolean 类型的值。polyfill实现如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Array.prototype.some = function (callbackfn, thisArg) {
let len = Number(this.length);
let k = 0;
while (k < len) {
let Pk = String(k);
if (Pk in this) {
let kValue = this[Pk];
if (callbackfn.call(thisArg, kValue, k, this)) {
return true;
}
}
k++;
}
return false;
};

可以看出,遇到回调返回值是 true 的话,函数就直接返回、结束了。这是种短路算法,并不是所有回调都执行一遍,然后再最后求所有与值。every 也类似,不过与之相反,遇到回调返回值是 false 时,整体就直接返回 false 了。
从实现上表达出的语义来讲,some 是在说:有一个成功,我就成功,而 every 是在说:有一个失败,我就失败
另外要强调一点,对于稀疏数组,不存在的索引值时,回调函数是不执行的

参考

Array.prototype.some() > 不再写 break 和 continue 了