循环和迭代
循环和迭代
« 上一步
下一步 »
循环提供了一种快速简便的方法来重复执行某些操作。本节介绍 JavaScript 指南中可用的不同迭代语句。
您可以将循环视为计算机化的游戏版本,您告诉某人向一个方向走 *X* 步,然后向另一个方向走 *Y* 步。例如,想法“向东走五步”可以用循环这样表达
jsfor (let step = 0; step < 5; step++) {
// Runs 5 times, with values of step 0 through 4.
console.log("Walking east one step");
}
循环有很多种,但它们基本上都做同样的事情:重复执行某个操作若干次。(注意,这个数字可能是零!)
各种循环机制提供了不同的方法来确定循环的起点和终点。有各种情况更容易通过一种类型的循环而不是其他类型来处理。
JavaScript 提供的循环语句是
for 语句
do...while 语句
while 语句
带标签的语句
break 语句
continue 语句
for...in 语句
for...of 语句
for 语句一个 for 循环会一直重复执行,直到指定条件计算结果为 false。JavaScript for 循环类似于 Java 和 C for 循环。
for 语句的格式如下
jsfor (initialization; condition; afterthought)
statement
当 for 循环执行时,会发生以下情况
执行初始化表达式 initialization(如果有)。此表达式通常初始化一个或多个循环计数器,但语法允许任意复杂度的表达式。此表达式还可以声明变量。
计算 condition 表达式。如果 condition 的值为 true,则执行循环语句。否则,for 循环终止。(如果完全省略 condition 表达式,则假定条件为 true。)
执行 statement。要执行多个语句,请使用 块语句 ({ }) 对这些语句进行分组。
如果存在,则执行更新表达式 afterthought。
控制返回步骤 2。
示例在下面的示例中,函数包含一个 for 语句,该语句计算滚动列表中所选选项的数量(允许进行多项选择的
HTML
html
JavaScript
这里,for 语句声明变量 i 并将其初始化为 0。它检查 i 是否小于
jsfunction countSelected(selectObject) {
let numberSelected = 0;
for (let i = 0; i < selectObject.options.length; i++) {
if (selectObject.options[i].selected) {
numberSelected++;
}
}
return numberSelected;
}
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
const musicTypes = document.selectForm.musicTypes;
console.log(`You have selected ${countSelected(musicTypes)} option(s).`);
});
do...while 语句do...while 语句会重复执行,直到指定条件计算结果为 false。
do...while 语句的格式如下
jsdo
statement
while (condition);
statement 始终在检查条件之前执行一次。(要执行多个语句,请使用块语句 ({ }) 对这些语句进行分组。)
如果 condition 为 true,则再次执行语句。在每次执行结束时,都会检查条件。当条件为 false 时,执行停止,控制权传递到 do...while 之后的语句。
示例在以下示例中,do 循环至少迭代一次,并重复迭代,直到 i 不再小于 5。
jslet i = 0;
do {
i += 1;
console.log(i);
} while (i < 5);
while 语句while 语句会执行其语句,只要指定条件计算结果为 true。while 语句的格式如下
jswhile (condition)
statement
如果 condition 变成 false,则循环内的 statement 停止执行,控制权传递到循环之后的语句。
条件测试发生在循环中执行 statement *之前*。如果条件返回 true,则执行 statement 并再次测试 condition。如果条件返回 false,则执行停止,控制权传递到 while 之后的语句。
要执行多个语句,请使用块语句 ({ }) 对这些语句进行分组。
示例 1以下 while 循环会一直迭代,只要 n 小于 3
jslet n = 0;
let x = 0;
while (n < 3) {
n++;
x += n;
}
每次迭代时,循环都会增加 n 并将该值添加到 x。因此,x 和 n 会获得以下值
第一次通过后:n = 1 且 x = 1
第二次通过后:n = 2 且 x = 3
第三次通过后:n = 3 且 x = 6
完成第三次通过后,条件 n < 3 不再为 true,因此循环终止。
示例 2避免无限循环。确保循环中的条件最终变成 false——否则,循环将永远不会终止!以下 while 循环中的语句会永远执行,因为条件永远不会变成 false
js// Infinite loops are bad!
while (true) {
console.log("Hello, world!");
}
带标签的语句label 为语句提供一个标识符,让您可以在程序中的其他位置引用该标识符。例如,您可以使用标签来标识循环,然后使用 break 或 continue 语句来指示程序是否应该中断循环或继续执行。
带标签语句的语法如下
jslabel:
statement
label 的值可以是任何 JavaScript 标识符,但不能是保留字。您使用标签标识的 statement 可以是任何语句。有关使用带标签语句的示例,请参阅下面的 break 和 continue 示例。
break 语句使用 break 语句来终止循环、switch 或与带标签语句一起使用。
当您在没有标签的情况下使用 break 时,它会立即终止最内层的封闭 while、do-while、for 或 switch,并将控制权转移到接下来的语句。
当您在有标签的情况下使用 break 时,它会终止指定的带标签语句。
break 语句的语法如下
jsbreak;
break label;
语法的第一种形式会终止最内层的封闭循环或 switch。
语法的第二种形式会终止指定的封闭带标签语句。
示例 1以下示例迭代数组中的元素,直到找到值为 theValue 的元素的索引
jsfor (let i = 0; i < a.length; i++) {
if (a[i] === theValue) {
break;
}
}
示例 2:跳到标签jslet x = 0;
let z = 0;
labelCancelLoops: while (true) {
console.log("Outer loops:", x);
x += 1;
z = 1;
while (true) {
console.log("Inner loops:", z);
z += 1;
if (z === 10 && x === 10) {
break labelCancelLoops;
} else if (z === 10) {
break;
}
}
}
continue 语句continue 语句可以用来重新启动 while、do-while、for 或 label 语句。
当您在没有标签的情况下使用 continue 时,它会终止最内层的封闭 while、do-while 或 for 语句的当前迭代,并继续执行循环的下一个迭代。与 break 语句不同,continue 不会完全终止循环的执行。在 while 循环中,它会跳回到条件。在 for 循环中,它会跳到 increment-expression。
当您在有标签的情况下使用 continue 时,它适用于使用该标签标识的循环语句。
continue 语句的语法如下
jscontinue;
continue label;
示例 1以下示例显示了一个带有 continue 语句的 while 循环,该语句在 i 的值为 3 时执行。因此,n 的值为 1、3、7 和 12。
jslet i = 0;
let n = 0;
while (i < 5) {
i++;
if (i === 3) {
continue;
}
n += i;
console.log(n);
}
// Logs:
// 1 3 7 12
如果您注释掉 continue;,循环将运行到最后,您将看到 1,3,6,10,15。
示例 2一个名为checkiandj的语句包含一个名为checkj的语句。如果遇到continue,程序将终止checkj的当前迭代并开始下一个迭代。每次遇到continue时,checkj都会重复迭代,直到其条件返回false。当返回false时,checkiandj语句的剩余部分将完成,并且checkiandj会重复迭代,直到其条件返回false。当返回false时,程序将在checkiandj之后的语句处继续执行。
如果continue有一个名为checkiandj的标签,程序将在checkiandj语句的顶部继续执行。
jslet i = 0;
let j = 10;
checkiandj: while (i < 4) {
console.log(i);
i += 1;
checkj: while (j > 4) {
console.log(j);
j -= 1;
if (j % 2 === 0) {
continue checkj;
}
console.log(j, "is odd.");
}
console.log("i =", i);
console.log("j =", j);
}
for...in 语句for...in 语句会将指定的变量迭代到对象的全部可枚举属性。对于每个不同的属性,JavaScript都会执行指定的语句。for...in 语句的格式如下所示:
jsfor (variable in object)
statement
示例下面的函数以一个对象和对象的名称作为参数。然后,它会遍历对象的所有属性,并返回一个字符串,其中列出了属性名称及其值。
jsfunction dumpProps(obj, objName) {
let result = "";
for (const i in obj) {
result += `${objName}.${i} = ${obj[i]}
`;
}
result += "
";
return result;
}
对于一个具有make和model属性的car对象,result将是:
car.make = Ford
car.model = Mustang
数组虽然可能会想要用它来遍历Array元素,但for...in语句会返回用户定义属性的名称以及数值索引。
因此,在遍历数组时,最好使用传统的for循环以及数值索引,因为for...in语句会遍历用户定义的属性,以及数组元素,如果您修改了Array对象(例如,添加自定义属性或方法)。
for...of 语句for...of 语句会创建一个循环,它会遍历可迭代对象(包括Array、Map、Set、arguments对象等),并使用要为每个不同属性的值执行的语句调用自定义迭代钩子。
jsfor (variable of iterable)
statement
下面的示例展示了for...of循环和for...in循环之间的区别。for...in循环遍历属性名,而for...of循环遍历属性值。
jsconst arr = [3, 5, 7];
arr.foo = "hello";
for (const i in arr) {
console.log(i);
}
// "0" "1" "2" "foo"
for (const i of arr) {
console.log(i);
}
// Logs: 3 5 7
for...of和for...in语句也可以和解构赋值一起使用。例如,您可以使用Object.entries()同时遍历对象的键和值。
jsconst obj = { foo: 1, bar: 2 };
for (const [key, val] of Object.entries(obj)) {
console.log(key, val);
}
// "foo" 1
// "bar" 2
« 上一步
下一步 »