大家好!上节课我们学会了让程序“动脑子”做决策(if/else),但有时候,我们需要让程序反复做同一件事——比如从1数到100,或者遍历一个列表。如果用手写100遍console.log(1)、console.log(2)……那不得累死?程序员最讨厌的就是重复劳动,所以就有了循环。
循环就是程序的“复读机”,你告诉它干啥、干多少遍,它就老老实实一遍遍执行,直到你喊停。今天我们就来认识三种循环:while、do...while和for。
想象一下这些场景:
循环就是这种“只要条件成立,就一直重复”的逻辑。
while循环的语法最简单:
while (条件) { // 循环体:要重复执行的代码 }
它的执行流程是:
判断条件(结果是布尔值,或者被转成布尔值)。
如果条件为真,执行循环体,然后回到第1步。
如果条件为假,跳出循环,继续往后执行。
// 从1数到5 let i = 1; while (i <= 5) { console.log(i); i++; // 千万别忘了更新变量,否则会死循环 }
输出:1 2 3 4 5
注意:循环体里一定要有改变条件的语句(比如i++),否则条件永远为真,就成了死循环——程序会卡死,甚至崩溃。如果你不小心写出了死循环,别慌,关掉浏览器标签页或者重启控制台就行。
while很适合用在不知道要循环多少次的情况,比如等待用户输入正确密码:
let password; while (password !== '123456') { password = prompt('请输入密码:'); } console.log('密码正确,欢迎进入!');
只要用户输入的密码不是'123456',就会一直弹窗询问,直到输入正确。
do...while和while很像,区别在于:它先执行一次循环体,再判断条件。所以无论条件是否成立,循环体至少执行一次。
do { // 循环体 } while (条件);
举个栗子:
let i = 10; do { console.log('这次肯定执行'); i++; } while (i < 5);
输出一次“这次肯定执行”,因为先执行后判断,i=10,条件10<5为假,结束。
这种循环适合那些“不管怎样,先干一次再说”的场景,比如展示菜单,然后根据用户选择决定是否继续。
for循环把循环需要的三要素(初始化、条件、更新)都写在一行,结构清晰,是遍历次数已知的情况的首选。
for (初始化; 条件; 更新) { // 循环体 }
执行顺序:
执行初始化(只执行一次,通常用来声明循环变量)。
判断条件,如果为假,跳出循环;如果为真,执行循环体。
执行更新(通常改变循环变量)。
回到第2步。
// 从1数到5 for (let i = 1; i <= 5; i++) { console.log(i); }
是不是比while更紧凑?初始化let i=1只执行一次;然后判断i<=5,为真就执行console.log(i),然后i++,再判断……直到i=6 时条件为假退出。
但通常不建议省略,除非特殊情况。
有时候,我们想在循环中间提前退出,或者跳过某次循环。这时就需要break和continue。
break就像“急刹车”,一旦执行,循环立即结束,不再进行后续判断。
// 找到第一个大于10的数就停止 for (let i = 1; i <= 20; i++) { if (i > 10) { console.log('找到了,大于10的第一个数是:' + i); break; // 找到后就退出循环 } }
输出到11就停了,不会继续输出后面的数字。
continue就像“跳过广告”,只结束本次循环的后续代码,直接进入下一次循环。
// 输出1到10,但跳过5 for (let i = 1; i <= 10; i++) { if (i === 5) { continue; // 遇到5就跳过,不执行后面的 console.log } console.log(i); }
输出:1 2 3 4 6 7 8 9 10(没有5)
注意:continue在while里要小心,如果更新语句在continue后面,可能会导致死循环。所以for循环用continue更安全,因为更新语句在continue之后也会执行(因为它是循环结构的一部分)。
循环里面还可以套循环,就像俄罗斯套娃。外层循环每执行一次,内层循环就要完整跑一遍。
// 打印九九乘法表 for (let i = 1; i <= 9; i++) { let row = ''; for (let j = 1; j <= i; j++) { row += `${j}×${i}=${i * j} `; } console.log(row); }
外层循环控制行数(1到9),内层循环控制每行的列数。嵌套循环在处理二维数组、矩阵时特别有用。
忘了更新循环变量,或者条件永远为真,就会死循环。例如:
let i = 1; while (i <= 5) { console.log(i); // 忘了 i++ }
浏览器会卡死,赶紧关标签页。
用let在for循环里声明的变量,只在循环内有效;如果在外部也需要,要在外面声明。
for (let i = 0; i < 3; i++) { // i 只在这里有效 } console.log(i); // 报错:i is not defined
break跳出多层循环break只能跳出当前循环。如果想跳出多层嵌套循环,可以给循环加标签(label)。
outer: for (let i = 0; i < 3; i++) { for (let j = 0; j < 3; j++) { if (i === 1 && j === 1) { break outer; // 跳出外层循环 } console.log(`i=${i}, j=${j}`); } }
不过标签用得少,大多数情况下可以用函数封装或调整逻辑避免多层break。
循环最常见的用途是遍历数组(后面会详讲)。比如有一个数组['苹果', '香蕉', '橘子'],想输出每个元素:
let fruits = ['苹果', '香蕉', '橘子']; for (let i = 0; i < fruits.length; i++) { console.log(fruits[i]); }
此外,循环也常用于计算累加、累乘、查找最大值等。
for循环计算1到100的和。while循环输出10到1(倒序)。prompt不断输入数字,直到输入的是0为止,然后输出所有输入数字的和。(提示:用while)今天你学会了:
循环是编程的基石,很多算法都离不开它。下一节课,我们将学习函数——把一段代码打包起来,随用随调,真正实现“一次编写,到处运行”。你将学会如何创建自己的“工具包”,告别重复代码。
记得完成练习,下节课见!
课后作业:
for循环输出1到100之间所有能被3整除的数。while循环实现一个猜数字游戏:程序随机生成一个1-100的数字,用户输入猜测,提示“大了”、“小了”或“恭喜猜对”,直到猜对为止。(提示:用Math.random() 生成随机数)本文作者:aboss
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!