跳到内容

JavaScript/控制结构

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



大多数编程语言都由“积木”组成,例如标记(关键字、变量、运算符等)、表达式(例如 myArray.length + 1)、语句(用 ; 分隔)、块 {...}、函数和模块。乍一看,程序的执行遵循语句的顺序,从上到下。但在几乎所有情况下,程序都需要不按语句的严格顺序运行。相反,某些部分必须仅在满足特定条件时才运行,而其他部分将被省略并在不同的条件下运行。或者,可能需要某些部分重复执行。其他部分可能会并行运行,并在稍后同步。或者,不同模块的函数必须计算出值,然后才能执行下一个语句。

在这个“语言积木”的层次结构中,术语 **块** 对于理解程序流程至关重要。在 JavaScript 中,块是零个或多个语句(或较小的块)的序列,这些语句被大括号包围 { // 零个或多个语句 }。我们在这里讨论的语言结构会调用或重复块。

if / else

[编辑 | 编辑源代码]

if / else 语句(是的,它是一个单一语句,即使它在其块中包含其他语句)会根据条件的评估结果调用两个块之一的执行。评估返回一个 布尔值。如果为 true,则执行第一个块;如果为 false,则执行第二个块。另一个块将被跳过。

if ( condition ) {
  // block of statements
} else {
  // block of statements
}

else 部分是可选的,即可以使用 if 而没有 else 部分及其块。

if ( condition ) {
  // block of statements
}

一个例子

"use strict";
const a = 3;
const b = "3";
if (a == b) {
  alert("The two variables contain the same value, but may have different data types.");
} else {
  alert("The two variables contain different values.");
}

// an example without 'else'
const c = 6 / 2;
if (a === c) {
  alert("The two variables contains the same value and are of the same data type.");
}

如果两个块之一正好包含一条语句,则可以省略大括号。但为了代码清晰起见,我们建议使用带有大括号的统一语法。

// same as above; but this abbreviated syntax is not recommended.

"use strict";
const a = 3;
const b = "3";

if (a == b) alert("The two variables contains the same value, but may have different data types.");
else alert("The two variables contain different values.");

const c = 6 / 2;
if (a === c) alert("The two variables contains the same value and are of the same data type.");

在很多情况下,实际情况需要比简单的真/假替代更复杂的决策。例如,您可能想知道一个数字是负数、零还是正数。在这种情况下,解决方案可能如下所示

"use strict";
const x = 3;

if (x < 0) {
  alert("The number is negative.");
} else {
  // x is equal or greater than 0
  if (x === 0) {
    alert("The number zero.");
  } else {
    alert("The number is positive.");
  }
}

您可以缩短这段代码,而不会失去清晰度。因为第一个 else 块仅包含一条语句 - 即第二个 if - 您可以省略其大括号并将第一个 else 和第二个 if 合并为一行。

"use strict";
const x = 3;

if (x < 0) {
  alert("The number is negative.");
} else if (x === 0) {
  alert("The number is zero.");
} else {
  alert("The number is positive.");
}

这是一个清晰且经常使用的编程风格。它用于您有可管理的选项数量或必须使用多个变量进行决策的情况。

如果决策数量大幅增加,则使用 switch 语句而不是长长的 else if 条件列表会使代码更清晰。

switch 语句会评估表达式,并根据其结果与 case 关键字后面的标签的比较来引导语句的流程。

"use strict";

const myVar = "a";

// evaluation takes simple variables as well as complex expressions
switch (myVar.toUpperCase()) {
case "A":
  // …
  break;
case "B":
  // …
  break;
default:   // analog to 'else' without any further 'if'
  // …
  break;
}

如果评估结果与其中一个标签匹配,JavaScript 会执行从下一个 break 或整个 switch 的末尾开始的以下语句。如果没有任何标签匹配,则执行会继续在 default 标签处,或者 - 如果不存在 - 完全跳过 switch 语句。

标签是字面量或表达式;例如,case (2 + 1).toString(): 是可能的。

一旦遇到 break 语句,switch 的执行就会终止。通常它出现在每个 case 的末尾,以防止执行以下 case 的代码。但如果故意要执行它们,则可以省略它。在以下示例中,相同的代码将针对 i 等于 1、2 或 3 运行。

"use strict";

const i = 2;

switch(i) {
case 1:
case 2:
case 3:
  // …
  break;
case 4:
  // …
  break;
default:
  // …
  break;
}

因为要评估的表达式以及标签可以是复杂的表达式,所以可以构建非常灵活的结构。

"use strict";

const i = 2;

switch(true) { // in this example it's a constant value
case (i < 10):
  alert("one digit");
  break;
case (i >= 10 && i < 100):
  alert("two digits");
  break;
default:
  // …
  break;
}


continue 关键字不适用于 switch 语句。

try / catch / finally

[编辑 | 编辑源代码]

如果存在运行时错误可能发生的可能性,您可以“捕获”该错误并执行有意义的操作来处理这种情况。例如,网络连接或数据库可能不再可用;用户输入导致零除;… .

try {
  // critical block where errors might occur
} catch (err) {
  // block to handle possible errors. Normally not executed.
} finally {
  // block that will be executed in ALL cases
}
"use strict";

const x = 15;
let average;
try {
  // block with critical statements
  x = x + 5;
  average = x / 0;
  alert("The average is: " + average);
} catch (err) {
  // block to handle possible errors
  alert("Something strange occurs. The error is: " + err);
} finally {
  // block that will be executed in ALL cases
  alert("End of program.");
}

如果 关键 块中的某个语句引发运行时错误,则会省略其剩余语句的执行。相反,执行会调用 catch 块。最后,执行 finally 块。

请注意,finally 块在所有情况下都会执行,无论是否发生运行时错误。这甚至适用于 关键catch 块执行 return 语句的情况。

在上面的示例中,JavaScript 引擎会自行抛出异常。在其他情况下,JavaScript 引擎以某种方式或其他方式进行操作,但您可能希望看到它以不同的方式处理。例如,在零除的情况下,引擎不会抛出错误;它会将 Infinity 分配给结果,并跳到下一条语句。如果您想要不同的行为,则可以创建和抛出自己的程序异常。

"use strict";

const x = 15;
let average;
try {
  // block with critical statements
  average = x / 0;
  // or: const z = "abc"; average = z / 0;
  if (average === Infinity || Number.isNaN(average)) {
    // Throw your own exception with any text
    throw "Error during division. The result is: " + average;
  }
  alert("The average is: " + average);
} catch (err) {
  // block to handle possible errors
  alert("Something strange occurs. The error is: " + err);
} finally {
  // block that will be executed in ALL cases
  alert("End of program.");
}

如果发生异常 - 由 JavaScript 引擎或您的程序生成,并且没有被 catch 块捕获 - 脚本会终止,或者 - 如果它是函数 - 它会将控制权返回给调用函数。错误处理可以在那里或在调用它的函数之一中实现。

"use strict";

const answer = prompt("How old are you?");
const age = Number(answer);

if (isNaN(age)) {
  throw answer + " cannot be converted to a number.";
  // The script terminates with this message (it's not a function)
}
alert("Next year you will be " + (age + 1));
… 在另一个页面提供(点击这里)。

循环和迭代是其他情况,在这些情况下,语句的顺序流程由周围的语言结构进行操作。这将在下一页中进行描述。

另请参阅

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