现代 JavaScript 教程 — while 和 for 循环

循环:while 和 for

咱们常常须要重复执行一些操做。javascript

例如,咱们须要将列表中的商品逐个输出,或者运行相同的代码将数字 1 到 10 逐个输出。html

循环 是一种重复运行同一代码的方法。java

"while" 循环

while 循环的语法以下:react

while (condition) {
  // 代码
  // 所谓的“循环体” 
}
复制代码

conditiontrue 时,执行循环体的 code算法

例如,如下将循环输出当 i < 3 时的 i 值:浏览器

let i = 0;
while (i < 3) { // 依次显示 0、1 和 2
  alert( i );
  i++;
}
复制代码

循环体的单次执行叫做 一次迭代。上面示例中的循环进行了三次迭代。bash

若是上述示例中没有 i++,那么循环(理论上)会永远重复执行下去。实际上,浏览器提供了阻止这种循环的方法,咱们能够经过终止进程,来停掉服务器端的 JavaScript。服务器

任何表达式或变量均可以是循环条件,而不只仅是比较。在 while 中的循环条件会被计算,计算结果会被转化为布尔值。微信

例如,while (i != 0) 可简写为 while (i)学习

let i = 3;

while (i) { // 当 i 变成 0 时,条件为 false,循环终止
  alert( i );
  i--;
}
复制代码

单行循环体不须要大括号:

若是循环体只有一条语句,则能够省略大括号 {…}

let i = 3;

while (i) alert(i--);
复制代码

"do..while" 循环

使用 do..while 语法能够将条件检查移至循环体 下面

do {
  // 循环体
} while (condition);
复制代码

循环首先执行循环体,而后检查条件,当条件为真时,重复执行循环体。

例如:

let i = 0;
do {
  alert( i );
  i++;
} while (i < 3);
复制代码

这种形式的语法不多使用,除非你但愿无论条件是否为真,循环体 至少执行一次。一般咱们更倾向于使用另外一个形式:while(…) {…}

"for" 循环

for 循环更加复杂,但它是最常使用的循环形式。

for 循环看起来就像这样:

for (begin; condition; step) {
  // ……循环体……
}
复制代码

咱们经过示例来了解一下这三个部分的含义。下述循环从 i 等于 03(但不包括 3)运行 alert(i)

for (let i = 0; i < 3; i++) { // 结果为 0、一、2
  alert(i);
}
复制代码

咱们逐个部分分析 for 循环:

语句段
begin i = 0 进入循环时执行一次。
condition i < 3 在每次循环迭代以前检查,若是为 false,中止循环。
body(循环体) alert(i) 条件为真时,重复运行。
step i++ 在每次循环体迭代后执行。

通常循环算法的工做原理以下:

开始运行
→ (若是 condition 成立 → 运行 body 而后运行 step)
→ (若是 condition 成立 → 运行 body 而后运行 step)
→ (若是 condition 成立 → 运行 body 而后运行 step)
→ ...
复制代码

因此,begin 执行一次,而后进行迭代:每次检查 condition 后,执行 bodystep

若是你这是第一次接触循环,那么回到这个例子,在一张纸上重现它逐步运行的过程,可能会对你有所帮助。

如下是在这个示例中发生的事:

// for (let i = 0; i < 3; i++) alert(i)

// 开始
let i = 0
// 若是条件为真,运行下一步
if (i < 3) { alert(i); i++ }
// 若是条件为真,运行下一步
if (i < 3) { alert(i); i++ }
// 若是条件为真,运行下一步
if (i < 3) { alert(i); i++ }
// ……结束,由于如今 i == 3
复制代码

内联变量声明

这里“计数”变量 i 是在循环中声明的。这叫作“内联”变量声明。这样的变量只在循环中可见。

for (let i = 0; i < 3; i++) {
  alert(i); // 0, 1, 2
}
alert(i); // 错误,没有这个变量。
复制代码

除了定义一个变量,咱们也可使用现有的变量:

let i = 0;

for (i = 0; i < 3; i++) { // 使用现有的变量
  alert(i); // 0, 1, 2
}

alert(i); //3,可见,由于是在循环以外声明的
复制代码

省略语句段

for 循环的任何语句段均可以被省略。

例如,若是咱们在循环开始时不须要作任何事,咱们就能够省略 begin 语句段。

就像这样:

let i = 0; // 咱们已经声明了 i 并对它进行了赋值

for (; i < 3; i++) { // 再也不须要 "begin" 语句段
  alert( i ); // 0, 1, 2
}
复制代码

咱们也能够移除 step 语句段:

let i = 0;

for (; i < 3;) {
  alert( i++ );
}
复制代码

该循环与 while (i < 3) 等价。

实际上咱们能够删除全部内容,从而建立一个无限循环:

for (;;) {
  // 无限循环
}
复制代码

请注意 for 的两个 ; 必须存在,不然会出现语法错误。

跳出循环

一般条件为假时,循环会终止。

但咱们随时均可以使用 break 指令强制退出。

例如,下面这个循环要求用户输入一系列数字,在输入的内容不是数字时“终止”循环。

let sum = 0;

while (true) {
  let value = +prompt("Enter a number", '');
  if (!value) break; // (*)
  sum += value;
}
alert( 'Sum: ' + sum );
复制代码

若是用户输入空行或取消输入,在 (*) 行的 break 指令会被激活。它马上终止循环,将控制权传递给循环后的第一行,即,alert

根据须要,"无限循环 + break" 的组合很是适用于没必要在循环开始/结束时检查条件,但须要在中间甚至是主体的多个位置进行条件检查的状况。

继续下一次迭代

continue 指令是 break 的“轻量版”。它不会停掉整个循环。而是中止当前这一次迭代,并强制启动新一轮循环(若是条件容许的话)。

若是咱们完成了当前的迭代,而且但愿继续执行下一次迭代,咱们就可使用它。

下面这个循环使用 continue 来只输出奇数:

for (let i = 0; i < 10; i++) {
  //若是为真,跳过循环体的剩余部分。
  if (i % 2 == 0) continue;
  alert(i); // 1,而后 3,5,7,9
}
复制代码

对于偶数的 i 值,continue 指令会中止本次循环的继续执行,将控制权传递给下一次 for 循环的迭代(使用下一个数字)。所以 alert 仅被奇数值调用。


continue 指令利于减小嵌套:

显示奇数的循环能够像下面这样:

for (let i = 0; i < 10; i++) {
  if (i % 2) {
    alert( i );
  }

}
复制代码

从技术角度看,它与上一个示例彻底相同。固然,咱们能够将代码包装在 if 块而不使用 continue

但在反作用方面,它多建立了一层嵌套(大括号内的 alert 调用)。若是 if 中代码有多行,则可能会下降代码总体的可读性。


注意:禁止 break/continue 在‘?’的右边

请注意非表达式的语法结构不能与三元运算符 ? 一块儿使用。特别是 break/continue 这样的指令是不容许这样使用的。

例如,咱们使用以下代码:

if (i > 5) {
  alert(i);
} else {
  continue;
}
复制代码

……用问号重写:

(i > 5) ? alert(i) : continue; // continue 不容许在这个位置
复制代码

……代码会中止运行,并显示有语法错误。

这只是不使用 ? 而不是 if 的另外一个缘由。


break/continue 标签

有时候咱们须要从一次从多层嵌套的循环中跳出来。

例如,下述代码中咱们的循环使用了 ij,从 (0,0)(3,3) 提示坐标 (i, j)

for (let i = 0; i < 3; i++) {

  for (let j = 0; j < 3; j++) {

    let input = prompt(`Value at coords (${i},${j})`, '');

    // 若是我想从这里退出并直接执行 alert('Done!')
  }
}

alert('Done!');
复制代码

咱们须要提供一种方法,以在用户取消输入时来中止这个过程。

input 以后的普通 break 只会打破内部循环。这还不够 —— 标签能够实现这一功能!

标签 是在循环以前带有冒号的标识符:

labelName: for (...) {
  ...
}
复制代码

break <labelName> 语句跳出循环至标签处:

outer: for (let i = 0; i < 3; i++) {

  for (let j = 0; j < 3; j++) {

    let input = prompt(`Value at coords (${i},${j})`, '');

    // 若是是空字符串或被取消,则中断并跳出这两个循环。
    if (!input) break outer; // (*)

    // 用获得的值作些事……
  }
}
alert('Done!');
复制代码

上述代码中,break outer 向上寻找名为 outer 的标签并跳出当前循环。

所以,控制权直接从 (*) 转至 alert('Done!')

咱们还能够将标签移至单独一行:

outer:
for (let i = 0; i < 3; i++) { ... }
复制代码

continue 指令也能够与标签一块儿使用。在这种状况下,执行跳转到标记循环的下一次迭代。


注意:标签并不容许“跳到”全部位置

标签不容许咱们跳到代码的任意位置。

例如,这样作是不可能的:

break label;  // 没法跳转到这个标签

label: for (...)
复制代码

只有在循环内部才能调用 break/continue,而且标签必须位于指令上方的某个位置。


总结

咱们学习了三种循环:

  • while —— 每次迭代以前都要检查条件。
  • do..while —— 每次迭代后都要检查条件。
  • for (;;) —— 每次迭代以前都要检查条件,可使用其余设置。

一般使用 while(true) 来构造“无限”循环。这样的循环和其余循环同样,均可以经过 break 指令来终止。

若是咱们不想在当前迭代中作任何事,而且想要转移至下一次迭代,那么可使用 continue 指令。

break/continue 支持循环前的标签。标签是 break/continue 跳出嵌套循环以转到外部的惟一方法。

做业题

先本身作题目再看答案。

1. 最后一次循环的值

重要程度:⭐️⭐️⭐

此代码最后一次 alert 值是多少?为何?

let i = 3;

while (i) {
  alert( i-- );
}
复制代码

2. while 循环显示哪些值?

重要程度:⭐️⭐️⭐️⭐

对于每次循环,写出你认为会显示的值,而后与答案进行比较。

如下两个循环的 alert 值是否相同?

  1. 前缀形式 ++i:

    let i = 0;
    while (++i < 5) alert( i );
    复制代码
  2. 后缀形式 i++

    let i = 0;
    while (i++ < 5) alert( i ); 复制代码

3. "for" 循环显示哪些值?

重要程度:⭐️⭐️⭐️⭐

对于每次循环,写下它将显示的值。而后与答案进行比较。

两次循环 alert 值是否相同?

  1. 后缀形式:

    for (let i = 0; i < 5; i++) alert( i );
    复制代码
  2. 前缀形式:

    for (let i = 0; i < 5; ++i) alert( i );
    复制代码

4. 使用 for 循环输出偶数

重要程度:⭐️⭐️⭐️⭐️⭐️

使用 for 循环输出从 210 的偶数。

5. 用 "while" 替换 "for"

重要程度:⭐️⭐️⭐️⭐️⭐️

重写代码,在保证不改变其行为的状况下,将 for 循环更改成 while(输出应保持不变)。

for (let i = 0; i < 3; i++) {
  alert( `number ${i}!` );
}
复制代码

6. 重复输入,直到正确为止

重要程度:⭐️⭐️⭐️⭐️⭐️

编写一个提示用户输入大于 100 的数字的循环。若是用户输入其余数值 —— 请他从新输入。

循环一直在请求一个数字,直到用户输入了一个大于 100 的数字,取消输入或输入了一个空行为止。

在这咱们假设用户只会输入数字。在本题目中,不须要对非数值输入进行特殊处理。

7. 输出素数(prime)

重要程度:⭐️⭐️⭐

大于 1 且不能被除了 1 和它自己之外的任何数整除的整数叫作素数

换句话说,n > 1 且不能被 1n 之外的任何数整除的整数,被称为素数。

例如,5 是素数,由于它不能被 234 整除,会产生余数。

写一个能够输出 2n 之间的全部素数的代码。

n = 10,结果输出 二、三、五、7

P.S. 代码应适用于任何 n,而不是对任何固定值进行硬性调整。

答案:

在微信公众号「技术漫谈」后台回复 1-2-12 获取本题答案。


现代 JavaScript 教程:开源的现代 JavaScript 从入门到进阶的优质教程。React 官方文档推荐,与 MDN 并列的 JavaScript 学习教程

在线免费阅读:zh.javascript.info


扫描下方二维码,关注微信公众号「技术漫谈」,订阅更多精彩内容。

相关文章
相关标签/搜索