JavaScript/循环
JavaScript 通过关键字 for
和 while
支持代码块的重复执行。Array
数据类型(以及类似的数据类型)的 forEach
方法提供了类似的行为。
for
语句的语法是:for (<初始表达式>; <条件>; <最终表达式>) { <代码块> }
。它的执行基于以下规则
初始表达式
被执行 - 对于整个for
语句只执行一次。通常,它声明并初始化一个或多个变量 - 通常是具有整数值的数字。有时变量的声明是在for
语句之上进行的。条件
被评估。如果它返回true
,则执行步骤 3。如果它返回false
,则for
语句终止。- 代码块被执行。
最终表达式
被执行。通常,它会递增或递减作为条件
部分的变量。- 循环从步骤 2 处重复。
for (let i = 0; i < 10; i++) {
// a block of statements
}
示例:显示偶数的平方系列;显示从 0 到 10 的数字的总和。
"use strict";
const upperLimit = 10;
let sum = 0;
let tmpString = "";
for (let i = 0; i <= upperLimit; i++) {
sum = sum + i;
if (i % 2 === 0) {
tmpString += i*i + "; "
}
}
alert ("The sum is: " + sum + ". The square numbers are: " + tmpString);
初始表达式
、条件
和 最终表达式
是可选的。如果您省略其中一个或多个,您的脚本将执行其他有用的语句来控制循环。以下是一些示例
"use strict";
// an infinite loop if you do not terminate it with 'break' (see below)
for (;;) {
// ...
break;
}
const answer = prompt("With which start value shall the loop begin?");
let i = Number(answer);
for (; i >= 0 && i < 10; i++) {
// the start value is computed above the loop
}
for (let i = 0; i < 10; ) {
// ...
if (true) { // an arbitrary other condition to control the increment
i++;
}
}
for
循环可以嵌套。您可以在第一个(或“外层”)循环的代码块中使用第二个(或“内层”)循环。
"use strict";
const maxInner = 10;
const maxOuter = 4;
let myString = "";
for (let o = 1; o <= maxOuter; o++) {
myString = "";
// Be careful. It's easy to confuse inner and outer loop variables.
for (let i = 1; i <= maxInner; i++) {
myString = myString + o*i + ", ";
}
alert(myString);
}
循环的这种嵌套在所有以下结构中也是可能的。
有时只有部分或整个代码块需要运行。这可以通过一个或多个 if / else
语句来实现。如果合适,可以使用关键字 continue
来缩短这种条件语句。如果遇到 continue
,则跳过代码块的剩余部分,并执行上面的步骤 4 最终表达式
。
"use strict";
for (let i = 0; i <= 6; i++) {
if (i === 5) {
continue; // skip the rest of the block
}
alert(i); // 0, 1, 2, 3, 4, 6
}
这个例子非常简单。它在 i
等于 5 的情况下跳过代码块的下部。当然,它也可以用其他方式表达。一个更现实的例子是遍历数据库搜索结果的循环,它跳过对具有特定状态的行进行复杂处理的部分。
break
关键字与 continue
关键字类似,但更严格。它不仅跳过代码块的剩余部分,而且还终止整个循环。
"use strict";
for (let i = 0; i <= 6; i++) {
if (i === 5) {
break; // terminal the loop
}
alert(i); // 0, 1, 2, 3, 4
}
一个现实的场景是遍历数据库搜索结果的循环,其中在循环的中间断开了与数据库的连接。
您可以在所有形式的循环中使用 continue
和 break
。
语句的语法是:do { <代码块> } while (<条件>)
。它的执行基于以下规则
- 代码块被执行。因为这是第一步,所以代码块至少执行一次。如果您想确保在任何情况下都发生某些事情,这将很有帮助。
条件
被评估。如果它返回true
,则再次调用步骤 1。如果它返回false
,则循环终止。请注意,没有专门的部分可以用来操作条件中检查的变量。这必须在代码块中与其他语句一起完成。
"use strict";
let counter = 100;
do {
counter++;
alert(counter); // ... or some logging
} while (counter < 10);
while (<条件>) { <代码块> }
的语法与之前的 do { <代码块> } while (<条件>)
非常相似。唯一的区别是条件是在代码块之前检查,而不是之后。
此语言结构用于遍历对象的属性。它的语法是:for (<变量> in <对象>) { <代码块> }
。变量接收对象的每个属性的 键 - 一个接一个。对于每个属性,代码块都执行一次。
"use strict";
const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};
for (const key in myObj) {
alert(key); // firstName, familyName, born
// alert(myObj[key]); // if you want to see the values
}
数组是专门的对象。因此,可以在数组上使用 for..in
。数组的键是整数,从 0 开始 - 这正是从数组中提取的内容。
"use strict";
const myArray = ["certo", "uno", "dos", "tres"];
for (const key in myArray) {
alert(key); // 0, 1, 2, 3
// alert(myArray[key]); // if you want to see the values
}
数组也接受非数字键,例如,myArray["four"] = "cuatro";
。for..in
循环处理这种非数字键 - 与下面的 for..of
循环相反,也与页面顶部的传统 for
循环相反。
另请参见:MDN:for..in
此语言结构用于遍历数组。它的语法是:for (<变量> of <可迭代对象>) { <代码块> }
。变量接收数组的所有 值 - 一个接一个。对于每个值,代码块都执行一次。
此定义听起来与上面 for..in
的定义类似。但它们之间存在显著的差异
- 它返回的是 值,而不是数组的 键 或 索引。
- 它只适用于所有 可迭代 对象(Array、Map、Set 等)。数据类型 'object' 不可迭代。
- 它只适用于数字类型的键。非数字类型的 键 或 索引 会被静默地忽略。
"use strict";
const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";
for (const myValue of myArray) {
alert(myValue); // cero, uno, dos, tres. No 'cuatro' because the key is a string.
}
另请参见:MDN:for..of
这两个语言结构的差异在示例中总结。
"use strict";
const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};
const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";
// for..of not allowed on true objects; only for..in is possible.
for (const x of myObj) {}; // error
for (const x in myArray) {
alert(x); // 0, 1, 2, 3, four
}
for (const x of myArray) {
alert(x); // cero, uno, dos, tres. NO cuatro!
}
如果您正在寻找一个循环来处理对象的键和值,则比上面显示的 for..in
与 myObj[key]
的组合更直接的方法。数据类型 Object 提供了 entries()
方法,该方法返回一个数组。该数组的每个元素都包含一个包含两个值的数组:属性键和属性值。换句话说:entries()
方法的返回值是一个二维数组。而且,与数组一样,您应该将其与 for..of
结合使用。
"use strict";
const myObj = {firstName: "Marilyn", familyName: "Monroe", born: 1953};
const myArray = ["cero", "uno", "dos", "tres"];
myArray["four"] = "cuatro";
for (const [key, val] of Object.entries(myObj)) {
alert(key + ' / ' + val);
}
for (const [key, val] of Object.entries(myArray)) {
alert(key + ' / ' + val); // 'four / cuatro' is included
}
提示:Object.entries()
以及以下 Array.forEach()
方法不是像关键字或 for..in
或 for..of
语言结构这样的“核心”语言元素。它们分别是 Object 和 Array 数据类型的方法。
数据类型 Array 提供了 forEach()
方法。它遍历数组的元素,依次返回一个元素。有趣的是,它以函数作为参数。这与各种 for
和 while
循环不同。此类函数通常称为 回调函数。
方法调用非常简单:myArray.forEach(myFunction)
。可能令人困惑的是,函数调用 可以用多种方式缩写。
第一个示例显示了显式函数调用。它定义了函数 myFunction,它也接受单个参数。当 myFunction 被 forEach() 调用时,下一个数组元素被插入到 myFunction 的参数中。
"use strict";
// function definition (the function is not called here!)
function myFunction(element) {
alert("The element of the array is: " + element)
};
// a test array
const myArray = ['a', 'b', 'c'];
// iterate over the array and invoke the function once per array element
myArray.forEach(myFunction);
以下示例显示了函数调用语法的一些缩写。
"use strict";
// the 'arrow' syntax
const myFunction =
(element) => {
alert("The element of the array is: " + element)
};
// same code without line breaks:
// const myFunction = (element) => {alert("The element of the array is: " + element)};
const myArray = ['a', 'b', 'c'];
myArray.forEach(myFunction);
"use strict";
const myArray = ['a', 'b', 'c'];
// Define the function directly as the argument of the forEach(). Such
// functions are called 'anonymous' functions.
myArray.forEach((element) => {alert("The element of the array is: " + element)});
"use strict";
const myArray = ['a', 'b', 'c'];
// in simple cases, more syntactical elements are optional
myArray.forEach(element => alert("The element of the array is: " + element));
使用哪种语法取决于您的偏好。
在许多情况下,被调用函数执行副作用,例如日志记录。要计算所有数组元素的值,有必要使用闭包 的技术。在以下示例中,变量 sum
未在外部上下文中定义,也不在匿名函数中定义。
"use strict";
const myArray = [3, 0, -1, 2];
let sum = 0;
myArray.forEach(element => sum = sum + element);
alert(sum);
总而言之,以下规则适用于 forAll()
方法
- 该方法可用于可迭代对象,如 Array、Map、Set。数据类型 Object 不可迭代。
- 该方法仅遍历具有数字键的元素,这是数组的常见情况。
另请参见