while

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

试试看

语法

js
while (condition)
  statement
条件

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

语句

只要条件计算结果为真,就会执行的语句。您可以使用块语句来执行多个语句。

描述

与其他循环语句一样,您可以在statement内使用控制流语句

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

示例

使用 while

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

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. 所以循环结束。

这行代码的问题在于:条件通常使用比较运算符(如===),但该行中的=不是比较运算符——而是赋值运算符。因此,该=看起来像===的错别字——即使它实际上不是错别字。

因此,在像那种情况下,一些代码 lint 工具(例如 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 语言规范
# sec-while-statement

浏览器兼容性

BCD 表格仅在浏览器中加载

另请参阅