跳至内容

JavaScript/循环

来自维基教科书,开放世界中的开放书籍



JavaScript 通过关键字 forwhile 支持代码块的重复执行。Array 数据类型(以及类似的数据类型)的 forEach 方法提供了类似的行为。

for (;;) {}

[编辑 | 编辑源代码]

for 语句的语法是:for (<初始表达式>; <条件>; <最终表达式>) { <代码块> }。它的执行基于以下规则

  1. 初始表达式 被执行 - 对于整个 for 语句只执行一次。通常,它声明并初始化一个或多个变量 - 通常是具有整数值的数字。有时变量的声明是在 for 语句之上进行的。
  2. 条件 被评估。如果它返回 true,则执行步骤 3。如果它返回 false,则 for 语句终止。
  3. 代码块被执行。
  4. 最终表达式 被执行。通常,它会递增或递减作为 条件 部分的变量。
  5. 循环从步骤 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);
}

循环的这种嵌套在所有以下结构中也是可能的。

continue / break

[编辑 | 编辑源代码]

有时只有部分或整个代码块需要运行。这可以通过一个或多个 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
}

一个现实的场景是遍历数据库搜索结果的循环,其中在循环的中间断开了与数据库的连接。

您可以在所有形式的循环中使用 continuebreak

do {} while ()

[编辑 | 编辑源代码]

语句的语法是:do { <代码块> } while (<条件>)。它的执行基于以下规则

  1. 代码块被执行。因为这是第一步,所以代码块至少执行一次。如果您想确保在任何情况下都发生某些事情,这将很有帮助。
  2. 条件 被评估。如果它返回 true,则再次调用步骤 1。如果它返回 false,则循环终止。请注意,没有专门的部分可以用来操作条件中检查的变量。这必须在代码块中与其他语句一起完成。
"use strict";

let counter = 100;
do {
  counter++;
  alert(counter);  // ... or some logging
} while (counter < 10);

while () {}

[编辑 | 编辑源代码]

while (<条件>) { <代码块> } 的语法与之前的 do { <代码块> } while (<条件>) 非常相似。唯一的区别是条件是在代码块之前检查,而不是之后。

for (x in Object) {}

[编辑 | 编辑源代码]

此语言结构用于遍历对象的属性。它的语法是: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 (x of Array) {}

[编辑 | 编辑源代码]

此语言结构用于遍历数组。它的语法是: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

for..in 与 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!
}

Object.entries() 方法

[编辑 | 编辑源代码]

如果您正在寻找一个循环来处理对象的键和值,则比上面显示的 for..inmyObj[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..infor..of 语言结构这样的“核心”语言元素。它们分别是 ObjectArray 数据类型的方法。

Array.forEach() 方法

[编辑 | 编辑源代码]

数据类型 Array 提供了 forEach() 方法。它遍历数组的元素,依次返回一个元素。有趣的是,它以函数作为参数。这与各种 forwhile 循环不同。此类函数通常称为 回调函数

方法调用非常简单: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() 方法

  • 该方法可用于可迭代对象,如 ArrayMapSet。数据类型 Object 不可迭代。
  • 该方法仅遍历具有数字键的元素,这是数组的常见情况。

另请参见

MDN:forEach()
MDN:迭代方法
...在另一个页面上提供(点击这里)。

另请参见

[编辑 | 编辑源代码]
华夏公益教科书