while

Baseline 已广泛支持

此特性已相当成熟,可在许多设备和浏览器版本上使用。自 ⁨2015 年 7 月⁩以来,各浏览器均已提供此特性。

while 语句创建一个循环,只要测试条件评估为真,就会执行指定的语句。条件在执行语句之前进行评估。

试一试

let n = 0;

while (n < 3) {
  n++;
}

console.log(n);
// Expected output: 3

语法

js
while (condition)
  statement
条件

在每次循环通过之前评估的表达式。如果此条件评估为真,则执行 statement。当条件评估为假时,执行将继续 while 循环之后的语句。

statement

只要条件评估为真,就执行的语句。您可以使用块语句来执行多个语句。

描述

像其他循环语句一样,你可以在 statement 中使用控制流语句

  • break 会停止 statement 的执行,并跳转到循环之后的第一条语句。
  • continue 停止 statement 执行并重新评估 condition

示例

使用 while

以下 while 循环只要 n 小于 3 就会迭代。

js
let n = 0;
let x = 0;

while (n < 3) {
  n++;
  x += n;
}

每次迭代,循环都会增加 n 并将其添加到 x。因此,xn 的值如下

  • 第一次通过后:n = 1 和 x = 1
  • 第二次通过后:n = 2 和 x = 3
  • 第三次通过后:n = 3 和 x = 6

完成第三次通过后,条件 n < 3 不再为真,因此循环终止。

使用赋值作为条件

在某些情况下,将赋值作为条件可能是有意义的。这会带来可读性方面的权衡,因此有一些样式建议可以使该模式对所有人来说更明显。

考虑以下示例,它迭代文档的注释,并将它们记录到控制台。

js
const iterator = document.createNodeIterator(document, NodeFilter.SHOW_COMMENT);
let currentNode;
while (currentNode = iterator.nextNode()) {
  console.log(currentNode.textContent.trim());
}

这并不是一个完全好的实践示例,特别是由于以下行

js
while (currentNode = iterator.nextNode()) {

该行的效果很好——每次找到注释节点时

  1. iterator.nextNode() 返回该注释节点,该节点被赋值给 currentNode
  2. 因此,currentNode = iterator.nextNode() 的值是真值
  3. 因此 console.log() 调用执行并且循环继续。

……然后,当文档中没有更多注释节点时

  1. iterator.nextNode() 返回null
  2. 因此,currentNode = iterator.nextNode() 的值也是 null,这是假值
  3. 所以循环结束。

该行的问题是:条件通常使用比较运算符,例如 ===,但该行中的 = 不是比较运算符,而是赋值运算符。因此,那个 = 看起来像=== 的错字——尽管它实际上不是错字。

因此,在这种情况下,一些代码检查工具(例如 ESLint 的no-cond-assign 规则)为了帮助您发现可能的错字以便您可以修复它,将报告以下警告

期望条件表达式,却看到了赋值。

许多样式指南建议更明确地指示条件为赋值的意图。您可以通过将额外的括号作为分组运算符放在赋值周围来最小化地做到这一点

js
const iterator = document.createNodeIterator(document, NodeFilter.SHOW_COMMENT);
let currentNode;
while ((currentNode = iterator.nextNode())) {
  console.log(currentNode.textContent.trim());
}

事实上,这是 ESLint 的 no-cond-assign 的默认配置以及 Prettier 所强制的样式,因此您可能会在实际项目中经常看到这种模式。

有些人可能还会建议添加比较运算符,将条件变成明确的比较

js
while ((currentNode = iterator.nextNode()) !== null) {

还有其他方法可以编写这种模式,例如

js
while ((currentNode = iterator.nextNode()) && currentNode) {

或者,完全放弃使用 while 循环的想法

js
const iterator = document.createNodeIterator(document, NodeFilter.SHOW_COMMENT);
for (
  let currentNode = iterator.nextNode();
  currentNode;
  currentNode = iterator.nextNode()
) {
  console.log(currentNode.textContent.trim());
}

如果读者对赋值作为条件模式足够熟悉,所有这些变体都应该具有相同的可读性。否则,最后一种形式可能是最可读的,尽管它最冗长。

规范

规范
ECMAScript® 2026 语言规范
# sec-while-statement

浏览器兼容性

另见