当你不知道需要迭代多少次时
当你事先知道范围时,for 循环最合适:“执行 10 次”“遍历这个数组的每个索引”。while 循环用于另一种情况:一直做下去,直到某个东西发生变化。你不知道需要迭代多少次,只知道让你停下来的条件。
它的结构非常简单:
JavaScript 先计算括号里的条件。如果是真值,就执行代码块。然后再检查条件,一次又一次,直到它变成假值。漏掉 count++,条件就永远不会变化,你就陷入了无限循环。
思维模型:检查、执行、重复
要让 while 循环合理,需要满足三点:
- 条件依赖于某个东西。
- 循环体有办法改变这个东西。
- 条件最终会变成假。
缺了任何一点都会出问题。经典的 bug 就是忘了第 2 步:
let count = 0;
while (count < 5) {
console.log(count);
// forgot to increment count - loops forever
}
它会一直运行,直到你强行结束进程。如果发生在服务器上,会造成实实在在的损失。一定要问问自己:循环体里的什么东西会让条件变成假?
一个真实的使用场景:不知道何时停止
while 在这种情况下比 for 更合适。你在从某处取出数据项,在全部取完之前,你不知道一共有多少个:
shift() 会移除并返回第一项。只要队列里还有东西,循环就继续运行;队列空了,循环自然就退出了。你也可以用 for 循环来写,但那样就是在和问题的结构较劲,而 while 读起来就是你的意图。
do...while:先执行,再判断
do...while 把顺序反了过来:先执行循环体,再检查条件。这保证了至少会迭代一次:
即使条件一开始就是假,循环体也总会执行一次。对比普通的 while,条件为假就意味着一次都不迭代。
日常的使用场景:提示用户输入,校验答案,答案不对就再次提示。你总是至少要问一次,所以 do...while 正合适。
注意结束的 ) 后面有一个分号:和 while 与 for 不同,do...while 需要分号。
break:提前退出
break 会立即退出最近的一层循环。当自然的循环条件不太适合当前任务时,就用它来停止:
一旦执行了 break,循环里的其他代码都不会再执行,既不会执行循环体的剩余部分,也不会再检查条件。直接退出。
while (true) 配合 break
当停止条件写在循环体里比写在循环头部更容易表达时,就换一种结构:无限循环,完成后用 break 跳出。
两个出口:成功,以及一个安全上限。安全上限很重要。没有一定会执行的 break 路径的 while (true),就是一个随时会发生的无限循环。
continue:跳到下一次迭代
continue 会跳到下一次条件检查,跳过本次迭代循环体的剩余部分:
有一个坑:如果推动循环前进的那行代码位于 continue 之后,你就写出了一个无限循环。上面的例子中,n++ 在 continue 之前,所以是安全的。如果把它放到后面,n 就会永远卡在某个偶数上。
while 与 for:该用哪个
一条机械的经验法则:
- 计数或按索引遍历已知范围 →
for。for (let i = 0; i < arr.length; i++)把计数器初始化、条件和步进都写在一行里。 - 遍历集合 →
for...of。比自己管理索引更简洁。 - 循环直到某个状态发生变化 →
while。处理队列、轮询、读取数据流、重试直到成功。 - 至少执行一次 →
do...while。
理论上它们可以互换:任何 for 都能改写成 while,反之亦然。但选择和问题结构相匹配的那一种,能让代码不言自明。
无限循环:唯一的规则
每个 while 循环都需要清楚地回答一个问题:是什么让它停下来?
要么循环头部的条件最终会变成假,要么有一个一定会执行的 break。如果你指不出其中任何一个,这个循环就还没写完。
// Bad: condition never changes
let ready = false;
while (!ready) {
console.log("waiting...");
// nothing in here flips `ready`
}
// Good: the body affects the condition
let ready = false;
let checks = 0;
while (!ready) {
checks++;
if (checks >= 3) ready = true;
}
在浏览器中,无限循环会让标签页卡死。在 Node 中,它会让一个 CPU 核心满载运行,直到你结束进程。最好在发布之前就把它们揪出来。
下一节:for...of 与 for...in
while 处理的是“直到某个东西发生变化”的情况。对于逐项遍历数组、字符串和对象,JavaScript 还有两种专门为此设计的循环形式:for...of 和 for...in,接下来就讲它们。
常见问题
JavaScript 中的 while 循环是什么?
while 循环会在条件为真值时反复执行循环体。JavaScript 先检查条件,执行代码块,然后再次检查。如果第一次检查时条件就是假,循环体一次都不会执行。
while 和 do...while 有什么区别?
while 在执行循环体之前检查条件,所以可能一次都不执行。do...while 先执行一次循环体,再检查条件,所以它至少会执行一次。当第一次迭代必须无条件发生时,比如提示用户输入,就用 do...while。
如何在 JavaScript 中跳出 while 循环?
用 break 语句立即退出循环,或者用 continue 跳到下一次迭代。安全地实现 while (true) 循环靠的就是 break:一直循环,等循环体内满足某个条件时再跳出。