js 常见for循环以及跳出循环的总结

for语句

基本语法

for循环是大家非常熟悉的也经常用的一种写法,一个for语句的基本语法为

// 括号中的三个条件都可省略
for ([initialExpression]; [condition]; [incrementExpression])
  statement

condition为true时,执行顺序:

initialExpression->condition->statement->incrementExpression

  1. initialExpression

初始化表达式,可以是一个任意复杂度的表达式,也可以声明变量。

// 常见用法1
for(let i = 0; i < 3; i++) { ... }
// 常见用法2
for(let i = 0, j = 3; i < j; i++) { ... }
  1. condition

执行for循环的条件表达式,如果值为true,循环中的语句会被执行,如果值为false,for循环终止。如果condition语句被省略,默认为true。

// condition默认为true,所以下面语句会进入死循环
for(;;) { ... }
  1. statement

for循环的执行体。

  1. incrementExpression

更新表达式,一般用于更新循环变量,使得若干次循环后不满足条件而退出循环。

实例
for(let i = 0, j = 3; i < j; i++) {
    console.log(i);
}

while语句

基本语法
while (condition)
  statement

condition为true时,则执行statement,然后继续检查condition,如果为false,则跳出循环执行后面的语句,所以如果当condition一直为true时,则会进入死循环。

// 下面语句会进入死循环
while (true) {
  console.log('loop');
}
实例
let i = 0
while (i < 10) {
    i++;
    console.log(i)
}

do ... while语句

基本语法
do
  statement
while (condition);

while语句不同的是,不管条件如何,会首先执行一遍statement,然后再进行condition条件判断,如果为true则继续执行statement,如果为false则跳出循环执行后面的语句。

实例
let i = 0
do {
    i++;
    console.log(i)
} while (i < 10)

for ... in语句

基本语法

for ... in语句以任意顺序遍历一个对象的除Symbol以外的可枚举属性

for (variable in object) {
  statements
}

请注意:循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性。

实例
function parent(){
    this.x = 1;
    this.y = 2
}
parent.prototype = {
    a: 'a',
    b: 'b'
}
const child = new parent()
for(let key in child) {
    console.log(key)
}
// 输出
// x
// y
// a
// b

可以看到原型上的a,b属性也被遍历出来了,如果不想遍历继承的属性,则可以添加hasOwnProperty()判断

for(let key in child) {
    if (child.hasOwnProperty(key)) {
        console.log(key)
    }
}
// 输出
// x
// y

for ... of语句

基本语法

用于遍历可迭代对象,比如(ArrayMapSetString),可迭代对象简而言之就是原型对象都有一个 @@iterator方法,具体概念自行谷歌。

for (variable of iterable) {
    statements
}

Object不是可迭代对象,所以用for ... of遍历对象时则会报错。

const obj = {x: 1}
for(const v of obj){ console.log(v) }
// Uncaught TypeError: obj is not iterable
实例
const array = [1, 2, 3]
for( const value of array) {
    console.log(value)
}

循环map对象时,可以定义key值

const map = new Map([['x', 1], ['y', 2]])
for(const [k, v] of map) {
    console.log(k, v)
}
// 输出
// x 1
// y 2

中断循环

以上总共介绍了五种循环的方式,但每种方式该如何中断循环呢?下面来介绍中断循环的几种常见方式:breakcontinuereturn

label语句

首先介绍下label语句,这个语句不是用来中断循环的,而是一个语句标识符,为什么先介绍这个语句呢?因为后面介绍的breakcontinue语句后面都可以跟label这个参数,所以我们先看看label的用法。

基本语法
label :
   statement

label的值可以是任何的非保留字的 JavaScript 标识符, statement 可以是任意你想要标识的语句(块)。具体有什么用呢?我们看下面的例子

实例
break label
// 标记第一个循环语句
labelLoop:
for (let i = 0; i < 3; i++) {
    // 标记第二个循环语句
    labelLoop2:
    for(let j = 0; j < 3; j++) {
        if(i === 1 && j === 0) {
            break labelLoop; 
            // 直接跳出第一个循环,然后执行循环后面的语句
        }
        console.log(i, j);
    }
}
console.log('end loop')
// 输出
// 0 0
// 0 1
// 0 2
// end loop

可以看出有label标记后,可以直接跳出到标记循环外,执行循环后面的语句,如果没有label则默认跳出当前循环。

continue label
labelLoop:
for (let i = 0; i < 5; i++) {
    // 标记第二个循环语句
    labelLoop2:
    for(let j = 0; j < 5; j++) {
        if(i === 1 && j === 0) {
            continue labelLoop; 
            // 直接跳到第一个循环,然后执行第一个循环的下一次循环
        }
        console.log(i, j);
    }
}
console.log('end loop')
// 0 0
// 0 1
// 0 2
// 2 0
// 2 1
// 2 2
// end loop

可以看出有label标记后,可以直接跳出标记循环外,执行标记循环的下一次循环,如果没有label则默认跳出当前循环,并执行当前循环的下一循环。

break语句

终止循环或者switch语句

基本语法
break [label]

如果省略label则中断当前循环或者switch,如果有label,则终止指定的label语句

实例
  • for语句中断循环
for (let i = 0; i < 5; i++) {
    if(i > 2) { break; }
    console.log(i);
}
// 输出
// 0
// 1
// 2
  • while语句中断循环
let i = 0
while (i < 5) {
    if(i > 2) { break; }
    console.log(i);
    i++
}
// 输出
// 0
// 1
// 2
  • do ... while语句中断循环
let i = 0
do {
    if(i > 2) { break; }
    console.log(i);
    i++
} while (i < 5)
// 输出
// 0
// 1
// 2
  • for ... in语句中断循环
let obj = {x: 1, y: 2, z: 3}
for(let k in obj) {
    if(k === 'z') { break;}
    console.log(k)
}
// 输出
// x
// y
  • for ... of语句中断循环
const arr = [1, 2, 3, 4, 5]
for(let v of arr) {
    if(v > 2) { break; }
    console.log(v)
}
// 输出
// 1
// 2

breaklabel的实例请参考上方 break label 实例。

continue语句

continue语句用来跳过代码块的剩余部分并进入下一循环。

基本语法
continue [label]

如果省略label则中断当前循环并进入下一次循环,如果有label则进入被label标识的下一次循环语句。

实例
for (let i = 0; i < 3; i++) {
    if(i === 1) {
        continue;
    }
    console.log(i);
}
// 输出
// 0
// 2

continuelabel的实例请参考上方 continue label实例。其他几种循环的continue效果一致,就不在重复了。

return语句

return语句用于指定函数返回的值且return语句只能出现在函数体内。

function loop() {
    let i = 0
    while(i < 5) {
        if(i > 2) return
        console.log(i)
        i++
    }
    console.log('end')
}
loop()
// 输出
// 1
// 2

forEach语句

forEach()方法对数组的每个元素执行一次提供的函数。forEach是数组原型上的一个遍历方法,这里拿出来讲主要是因为这也是一个非常常见的循环方法,而且经常会跟上面的循环搞混。

主要区别在于:没有办法中止或者跳出 forEach() 循环,除了抛出一个异常。如果你需要跳出循环请考虑使用for ... of语句,或其他数组方法,比如:Array.prototype.every()Array.prototype.some()等。

function test() {
    var a = [1, 2, 3, 4, 5]
    a.forEach(v => {
        if(v===2) return
        console.log(v)
    })
    console.log('end')
}
test()
// 输出
// 1
// 3
// 4
// 5
// end

可以看出return无法中断forEach循环。

总结

  1. for ... in循环会遍历自身和原型上的可枚举属性。
  2. break表示跳出循环。
  3. continue表示跳出当前循环,然后进入下次循环。
  4. return用在函数体内,终止函数的执行,并返回一个指定的值给函数调用者。
  5. breakcontinuereturn都可用在forfor ... infor ... ofwhiledo ... while语句内。
  6. forEach语句除了抛出异常否则无法跳出循环,如果需要中断循环,则应考虑其他循环方式。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350

推荐阅读更多精彩内容