循环语句
所谓循环就是指某段代码被重复执行的过程。
循环的本质就是以某个变量为起始值,然后不断产生变化量,慢慢靠近终止条件的过程。所以,循环需要具备三要素:
- 变量起始值
- 终止条件(没有终止条件,循环会一直执行,造成死循环)
- 变化量(用自增或者自减)
注意:循环内的弹窗有断点的效果。
do-while语句
do-while
语句是一种后条件判断语句,即循环体中的代码执行后才会对退出条件进行求值。
换句话说:无论条件是否为真都会先进行循环体,也就是说循环体内的代码至少执行一次。
1do {
2 statement;
3} while (expression);
1let i = 0;
2do {
3 i += 2;
4} while (i < 10);
:::
使用场景
循环体代码在退出前至少要执行一次
while语句
while
语句是一种先条件判断语句,即先检测退出条件,再执行循环体内的代码。因此,while循环体内的代码有可能不会执行。
while跟if语句很像,都要满足小括号里的条件,只有当条件为true时才会执行代码块
while大括号里代码执行完毕后不会跳出,而是继续回到小括号里判断条件是否满足,若满足则继续执行大括号里面的代码,然后回到小括号判断条件,直到括号内条件不满足,即跳出。
1while (expression) statement;
1let i = 0;
2while (i < 10) {
3 i += 2;
4}
:::
for
for
语句也是一种先条件判断语句,只不过增加了进入循环之前的初始化代码,以及循环执行后要执行的表达式。
语法
1for(initialization; expression; post-loop-expression) statement;
1let count = 10;
2for (let i = 0; i < count; i++) {
3 console.log(i);
4}
以上代码在循环开始前定义了变量 i
的初始值为 0。然后求值条件表达式(i < count),如果求值结果为 true,则执行循环体。因此循环体也可能不会被执行。如果循环体被执行了,则循环后表达式也会执行,以便递增变量 i
。for循环跟下面的while循环是一样的:
1let count = 10;
2let i = 0;
3while (i < count) {
4 console.log(i);
5 i++;
6}
**无法通过while循环实现的逻辑,同样也无法通过for循环实现。**因此for循环只是将循环相关的代码封装在了一起而已。
TIP
在for循环的初始化代码中,其实是可以不使用变量声明关键字的。不过,初始化定义的迭代器变量在循环执行完成后几乎不可能再用到了。因此,最清晰的写法是使用let声明迭代变量,这样就可以将这个变量的作用域限定在循环中。
初始化、条件表达式和循环后表达式都不是必须的。因此,下面这种写法可以创建一个无穷循环:
1for (;;) {
2 doSomething();
3}
如果只包含条件表达式,那么for循环实际上就变成了while循环:
1let count = 10;
2let i = 0;
3for (; i < count; ) {
4 console.log(i);
5 i++;
6}
for循环嵌套
1//一个循环里再套一个循环,一般用在for循环里
2for(外部声明记录循环次数的变量; 循环条件; 变化值){
3 for(内部声明记录循环次数的变量; 循环条件; 变化值){
4 循环体
5 }
6}
for循环和while循环的区别
-
如果明确了循环的次数,推荐使用for循环
-
如果不明确循环的次数,推荐使用while循环
for-in语句
for-in
语句是一种严格的迭代语句,用于枚举对象中的非符号键属性。
1for (property in expression) statement;
1// 遍历对象
2let obj = {
3 name: "小苏同学",
4 url: "xiaosutongxue.com"
5};
6for (const key in obj) {
7 // key是对象的属性,obj[key]是对象中属性key对应的值
8 if (obj.hasOwnProperty(key)) {
9 console.log(obj[key]);
10 }
11}
12
13// 遍历数组
14let arr = ['钢铁侠', '绿巨人', '蜘蛛侠'];
15for (const key in arr) {
16 // key是数组的索引,arr[key]是数组中索引key对应的值
17 console.log(key); // 0 1 2
18 console.log(arr[key]); // 钢铁侠 绿巨人 蜘蛛侠
19}
与for循环一样,这里控制语句中的const也不是必须的,但为了确保这个局部变量不被修改,推荐使用const。
ECMAScript中对象的属性是无序的,因此 for-in
语句不能保证返回对象的属性的顺序。换句话说,所有可枚举的属性都会返回一次,但返回的顺序可能会因浏览器而异。
如果 for-in
循环要迭代的变量是 null
或 undefined
,则不执行循环体。
for-of语句
for-of
语句是一种严格的迭代语句,用于遍历可迭代对象的元素。
1for (property of expression) statement;
用来遍历 Arrays(数组)、Strings(字符串)、Maps(映射)、Sets(集合)等可迭代的数据结构。
与 for...in...
不同的是 for...of...
每次循环取其中的值而不是索引。
1// 遍历数组
2let arr = [1, 2, 3];
3for (const iterator of arr) {
4 console.log(iterator); // 1 2 3
5}
6
7// 遍历字符串
8let str = "xiaosutongxue";
9for (const iterator of str) {
10 console.log(iterator); // x i a o s u t o n g x u e
11}
与for循环一样,这里控制语句中的const也不是必须的,但为了确保这个局部变量不被修改,推荐使用const。
for-of
循环会按照可迭代对象的 next()
方法产生值的顺序迭代元素,如果尝试迭代的变量不支持迭代,则 for-of
语句会抛出错误。
标签语句
标签语句用于给语句加标签
标签(label)为程序定义位置,可以使用continue/break
跳到该位置。
1// i+n 大于 15 时退出循环
2outside: for (let i = 1; i <= 10; i++) {
3 inside: for (let n = 1; n <= 10; n++) {
4 if (n % 2 != 0) {
5 continue inside;
6 }
7 console.log(i, n);
8 if (i + n > 15) {
9 break outside;
10 }
11 }
12}
break 和 continue 语句
break
和 continue
语句为执行循环代码提供了更严格的控制手段。其中:
-
break
语句用于立即退出循环,强制执行循环后的下一条语句(循环体内 break后面的语句不再执行)。
-
continue
也用于立即退出循环,但会再次从循环顶部开始执行。(结束本次循环,继续下次循环)
1let num = 0;
2for (let i = 1; i < 10; i++) {
3 if (i % 5 == 0) {
4 break;
5 }
6 num++;
7}
8console.log(num); // 4
1let num = 0;
2for (let i = 1; i < 10; i++) {
3 if (i % 5 == 0) {
4 continue;
5 }
6 num++;
7}
8console.log(num); // 8
:::
break
和 continue
都可以使与标签语句一起使用,返回代码中特定的位置,这通常是在嵌套循环中。
1let num = 0;
2outermost: for (let i = 0; i < 10; i++) {
3 for (let j = 0; j < 10; j++) {
4 if (i == 5 && j == 5) {
5 break outermost;
6 }
7 num++;
8 }
9}
10console.log(num); // 55
1let num = 0;
2outermost: for (let i = 0; i < 10; i++) {
3 for (let j = 0; j < 10; j++) {
4 if (i == 5 && j == 5) {
5 continue outermost;
6 }
7 num++;
8 }
9}
10console.log(num); // 95
:::
with语句
with
语句的用途是将代码作用域设置为特定的对象。
1with (expression) statement;
使用 with
语句的主要场景是针对一个对象的反复操作,这时候将代码作用域设置为该对象能提供便利。
1let qs = location.search.substring(1);
2let hostName = location.hostname;
3let url = location.href;
4
5// 使用with语句的写法
6with (location) {
7 let qs = search.substring(1);
8 let hostName = hostname;
9 let url = href;
10}
这里 with
语句用于连接 location
对象。这意味着在这个语句内部,每个变量都会被认为是一个局部变量。如果没有找到该局部变量,则会搜索 location
对象,看它是否有一个同名的属性。如果有,则该变量会被求值为 location
对象的属性。
严格模式不允许使用 with
语句,否则会抛出错误。
with
语句影响性能且难于调试其中的代码,通常不推荐在产品代码中使用 with
语句。