continue: 只是停止了当前循环,继续执行后面的循环,当循环执行完继续执行fn函数里之后的语句
break: 结束整个循环体,跳出循环来继续执行fn函数里之后的语句
return: 停止这个循环,跳出循环并且停止执行fn函数里后边的语句
我们将用基本循环来说明,每个迭代打印i的值:
for (let i = 1; i <= 10; i++){
console.log(i);
}
//运行结果:
1
2
3
4
5
6
7
8
9
10
Continue
如果我们只想打印偶数怎么办? 在每次迭代中,我们可以检查i是否为奇数。 如果是这样,我们将使用continue语句停止执行当前迭代。如果i是偶数,我们可以继续操作,并console.log记录i的值。该代码如下所示:
for (let i = 1; i <= 10; i++){
if (i % 2 == 1) continue;
console.log(i);
}
//运行结果:
2
4
6
8
10
记住,当我们使用continue语句时,循环迭代立即停止执行。 因此,console.log代码永远不会对奇数执行。
Break
由于某些原因,这次我们希望在i为6时完全停止执行循环。为此,我们将插入另一个条件测试i,如果测试通过,我们将中断循环执行:
for (let i = 1; i <= 10; i++){
if (i == 6) break;
console.log(i);
}
//运行结果:
1
2
3
4
5
//说明:如果运行此代码,则循环会在测试i == 6之后立即停止执行。这意味着6将不会登录到控制台
嵌套循环
for (let i = 0; i < 5; i++) {
if (i % 2 == 0) continue;
for (let j = 0; j < 5; j++) {
if (j == 2) break;
console.log(`i = ${i}, j = ${j}`);
}
}
//运行结果:
i = 1,j = 0
i = 1,j = 1
i = 3,j = 0
i = 3,j = 1
Return
return关键字并不是专门用于跳出循环的,return的功能是结束一个方法。 一旦在循环体内执行到一个return语句,return语句将会结束该方法,循环自然也随之结束。与continue和break不同的是,return直接结束整个方法,不管这个return处于多少层循环之内。不再执行下面的代码(结束当前的方法 直接返回)
(function () {
for (let i = 0; i <= 10; i++) {
if(i === 3){
return;
}
console.log(i);
}
console.log("如果i等于3,不会运行到这里");
})();
//运行结果:
0
1
2
forEach如何跳出循环?
forEach() 的定义:对数组的每个元素执行一次提供的函数。
forEach中return/return false/return true 只用于跳过本次循环,而不是整个循环,所以使用return没有效果。
使用break语句会报错。
[0,1,2,3,4,5].forEach((item)=>{
if(item == 2) return;
console.log(item);
})
//运行结果:
0
1
3
4
5
MDN文档上明确说明forEach循环是不可以退出的。
引自MDN There is no way to stop or break a forEach() loop other than by throwing an exception. If you need such behavior, the forEach() method is the wrong tool.
注意: 没有办法中止或者跳出 forEach() 循环,除了抛出一个异常。如果你需要这样,使用 forEach() 方法是错误的。
若你需要提前终止循环,你可以使用:
简单循环
for...of 循环
Array.prototype.every()
Array.prototype.some()
Array.prototype.find()
Array.prototype.findIndex()
探究为什么break和return不行
const arr = [1, 2, 3, 4, 5];
for (let i = 0; i < arr.length; i++) {
const rs = (function(item) {
console.log(item);
if (item > 2) return false;
})(arr[i])
}
使用return语句相当于在每个自执行函数中将返回值复制给rs,但是实际对整个函数并没有影响。而使用break语句报错是因为再JS的解释器中break语句是不可以出现在函数体内的。
如何变通跳出forEach循环
MDN官方推荐的方法
every在碰到return false的时候,中止循环。some在碰到return ture的时候,中止循环。
var a = [1, 2, 3, 4, 5]
a.every(item=>{
console.log(item); //输出:1,2
if (item === 2) {
return false
} else {
return true
}
})
var a = [1, 2, 3, 4, 5]
a.some(item=> {
console.log(item); //输出:1,2
if (item === 2) {
return true
} else {
return false
}
})
其他方法
- 1 使用for循环或者for in 循环代替
- 2 使用throw抛出异常
try {
[1, 2, 3, 4, 5].forEach(function(item) {
if (item=== 2) throw item;
console.log(item);
});
} catch (e) {}
- 3 使用判断跑空循环
[1, 2, 3, 4, 5].forEach(function(item){
if(!this.tag){
console.log(item);
if(item===2){
this.tag=true;
}
}
},{})
- 4 修改索引
var array=[1, 2, 3, 4, 5]
array.forEach(item=>{
if (item == 2) {
array = array.splice(0);
}
console.log(item);
})
forEach的执行细节讲解:
- 1 遍历的范围在第一次执行callback的时候就已经确定,所以在执行过程中去push内容,并不会影响遍历的次数,这和for循环有很大区别,下面的两个案例一个会造成死循环一个不会。
var arr=[1,2,3,4,5]
//会造成死循环的代码
for(var i=0;i<arr.length;i++){
arr.push('a')
}
//不会造成死循环
arr.forEach(item=>arr.push('a'))
- 2 如果已经存在的值被改变,则传递给 callback 的值是 forEach 遍历到他们那一刻的值。
var arr=[1,2,3,4,5];
arr.forEach((item,index)=>{
console.log(`time ${index}`)
arr[index+1]=`${index}a`;
console.log(item)
})
- 3 已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift()),之后的元素将被跳过。
var array=[1, 2, 3, 4, 5]
array.forEach(item=>{
if (item == 2) {
array = array.splice(0);
}
console.log(item);
})
// 如果数组在迭代时被修改了,则其他元素会被跳过
var words = ['one', 'two', 'three', 'four'];
words.forEach(function(word) {
console.log(word);
if (word === 'two') {
words.shift();
}
});
//运行结果:
one
two
four