循环语句,也是流程控制语句中不可或缺的一种结构。在 JavaScript 中实现循环的方式有好几种,我们一个一个来看。
在具体介绍 JavaScript 中的循环之前,首先我们来明确一个问题,那就是为什么需要循环。这里举一个简单的例子,例如我们要设计一个程序,计算从 1 加到 10 的值,或许你会写出:
let i = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
console.log(i);
但是如果是从 1 加到 100 呢?或者是从 1 加到 1000 呢?显然这种方法就力不从心了。这个时候,就需要循环语句登场了。这里我们介绍 JavaScript 中的 3 种循环结构,while 循环,do…while 循环以及 for 循环。
while 循环是循环里面比较常见的一种循环,它的语法如下:
while(表达式){
// 循环体
}
含义:如果表达式成立,执行循环体,否则结束循环
while 循环示例:从 1 加到 100
let i = 1,sum = 0;
while(i <= 100){
sum += i;
i++;
}
console.log(sum); // 5050
所谓无穷循环,被被称之为死循环。这是在我们无法退出循环时会遇到的一种情况。一般来讲,我们在设计循环的时候需要为循环设计一个出口,这样才能在当不满足循环条件的时候退出循环。
如果没有正确的对循环设计一个出口,那么循环语句将无法退出,陷入到无穷循环,也就是死循环里面。所以我们在设计循环的时候,一定要注意正确的书写循环条件,以便循环能在执行一定次数以后退出。
首先执行一次循环体,然后检测循环条件表达式的值是否为"真",如果是真的话,则重复执行循环语句。
do…while 循环和前面两种循环语句略有区别,区别在于循环至少会执行一次。
它的一般形式为:
do{
// 执行语句;
}while(表达式);
举例:用 do…while 改写上面的程序
let i = 1,sum = 0;
do{
sum += i;
i++;
}while(i <= 100);
console.log(sum); // 5050
for 循环是所有循环里面最常见的一种循环。for 循环的一般形式为:
for(表达式1;表达式2;表达式3){
// 循环体
}
它执行的顺序为:首先执行表达式 1,然后进行表达式 2 的判断,如果表达式 2 成立,那么执行循环体,循环体执行结束后,进行表达式 3,然后回头再看表达式 2 是否成立,成立就执行循环体,不成立该循环就结束。
for 循环举例:用 for 循环实现从 1 加到 100
let sum = 0;
for(let i=1;i<=100;i++){
sum += i;
}
console.log(sum); // 5050
在 for 循环里面,每一个部分都是可选的,例如上面的代码,我们可以做如下的修改:
let i = 1,sum = 0;
for(;i<=100;){
sum += i;
i++;
}
console.log(sum); // 5050
最早的时候,在 JavaScript 里面就经常使用 for 循环来对数组进行遍历。示例如下:
let arr = [1,2,3,4,5];
for(let i=0;i<arr.length;i++){
console.log(arr[i]);
}
这里有一个小技巧,就是在使用 for 循环来遍历数组的时候,使用一个变量来存储数组的长度,这样可以大大提升程序的效率,因为不用每次都去重新计算数组的长度
let arr = [1,2,3,4,5];
for(let i=0,j=arr.length;i<j;i++){
console.log(arr[i]);
}
我们可以把一个循环放在另外一个循环里面,从而构成循环的嵌套。里面的循环称之为内层循环,外面的循环称之为外层循环。外层循环每循环一次,内层循环就把自己的全部循环执行完。
循环嵌套示例:打印九九乘法表
let str = "";
for (let i = 1; i <= 9; i++) {
for (let j = 1; j <= i; j++) {
str += `${i}*${j}=${i*j} `;
}
console.log(str);
str = "";
}
// 1*1=1
// 2*1=2 2*2=4
// 3*1=3 3*2=6 3*3=9
// 4*1=4 4*2=8 4*3=12 4*4=16
// 5*1=5 5*2=10 5*3=15 5*4=20 5*5=25
// 6*1=6 6*2=12 6*3=18 6*4=24 6*5=30 6*6=36
// 7*1=7 7*2=14 7*3=21 7*4=28 7*5=35 7*6=42 7*7=49
// 8*1=8 8*2=16 8*3=24 8*4=32 8*5=40 8*6=48 8*7=56 8*8=64
// 9*1=9 9*2=18 9*3=27 9*4=36 9*5=45 9*6=54 9*7=63 9*8=72 9*9=81
上面有提到使用 for 循环来遍历数组。一般来讲,遍历一维数组就用一个 for 循环就够了,而如果要遍历一个二维数组,就需要使用到 for 循环的嵌套,也就是双层 for 循环。而如果是三维数组,则需要使用到三层 for 循环,以此类推。
使用双层 for 循环遍历一个二维数组:
let arr = [
["Bill",20],
["Lucy",23],
["David",25],
["Lily",18]
];
for(let i=0;i<arr.length;i++){
for(let j=0;j<arr[i].length;j++){
console.log(arr[i][j]);
}
}
// Bill
// 20
// Lucy
// 23
// David
// 25
// Lily
// 18
break 语句我们在前面讲 switch 语句的时候已经见到过了,当时有讲到它的作用是跳出 switch 语句或者循环语句。有一点需要注意的是:break 语句不能直接作用于 if 语句,除非这个 if 语句是被嵌套在循环语句里面的。
//错误
if(条件){
//执行语句
break;
}
//正确
for(表达式1;表达式2;表达式3){
if(条件){
//执行语句
break;
}
}
结束本次循环(不是终止整个循环),即跳过循环体中 continue 语句后面的语句,开始下一次循环。
break 语句和 continue 语句的区别:continue 语句的意思是结束本次循环,break 语句是结束整个循环。具体示例如下:
for(1;2;3){
a;
b;
break; // 执行a,b后循环结束
c;
d;
}
continue 语句:
for(1;2;3){
a;
b;
continue; // 执行a,b以后结束本次循环
c;
d;
}
break 和 continue 在默认情况下,是终止掉离它最近的循环。特殊情况下,我们可以通过给每个循环取一个名字,然后通过名字来终止指定循环,示例如下:
// 给数组去重复
let arr = [1, 2, 2, 2, 3, 4, 5, 5, 6, 6, 7, 8];
let newArr = [];
outer: for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < newArr.length; j++) {
if (arr[i] === newArr[j]) {
continue outer; // 终止名字为outer的循环
}
}
newArr.push(arr[i]);
}
console.log(newArr);
在上面的代码中,我们要给 arr 这个数组去除重复,在 ECMAScript 6 出来之前,数组去重都需要开发人员自己来书写方法。
这里我们就利用了一种最简单的去重方式,用旧数组和新数组进行比较,如果新数组里面不含有旧数组里面的元素,则将此元素放入新的数组。当我们比较的时候,发现新数组里面已经存在此元素时,就直接 continue 结束外层的循环,进入外层循环的下一次循环。
所谓流程控制,主要就是用于控制整个程序的走向的。
条件语句可以分为单分支语句,双分支语句以及多分支语句。
三目运算符可以看作是双分支语句的一个 缩写形式。
switch 语句是一种结构更清晰的多分支语句。涉及到的关键字有 case,break 和 default。
常见的循环结构有 while 循环,do…while 循环和 for 循环。
循环中常见的关键字有 break 和 continue,需要注意两者之间的区别。