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

在这种“语言构件”的层次结构中,代码块(block)这一术语对于理解程序的执行流程至关重要。在 JavaScript 中,代码块是由零个或多个语句(或更小的代码块)组成的序列,这些语句被花括号 { // 零个或多个语句 } 包围。我们在这里讨论的语言结构会调用或重复执行代码块。

if / else

if / else 语句(是的,它是一个单一的语句,尽管它包含了其他语句的代码块)根据条件的评估结果来决定执行两个代码块中的一个。评估结果返回一个布尔值。如果为 true,则执行第一个代码块;如果为 false,则执行第二个代码块。相应的另一个代码块将被跳过。

if ( condition ) {
  // 语句块
} else {
  // 语句块
}

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

if ( condition ) {
  // 语句块
}

例如:

"use strict";
const a = 3;
const b = "3";
if (a == b) {
  alert("两个变量包含相同的值,但可能具有不同的数据类型。");
} else {
  alert("两个变量包含不同的值。");
}

// 没有 'else' 的示例
const c = 6 / 2;
if (a === c) {
  alert("这两个变量的值相同且数据类型相同。");
}

如果两个代码块之一仅包含 一个 语句,则可以省略花括号。但为了代码的清晰性,建议使用统一的带花括号的语法。

// 和上面的示例一样;但是这种简化语法并不推荐

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

if (a == b) alert("两个变量包含相同的值,但可能具有不同的数据类型。");
else alert("两个变量包含不同的值。");

const c = 6 / 2;
if (a === c) alert("这两个变量的值相同且数据类型相同。");

在许多情况下,情况要求做出比简单的 true/false 判断更复杂的决策。例如,你可能想知道一个数字是负数、零还是正数。在这种情况下,可以采用以下解决方案:

"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 is 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 语句

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

switch 语句会评估一个表达式,并根据该表达式的结果与 case 后面的标签进行比较,决定执行的语句流。

"use strict";

const myVar = "a";

// 评估既可以是简单变量,也可以是复杂表达式
switch (myVar.toUpperCase()) {
case "A":
  // ...
  break;
case "B":
  // ...
  break;
default:   // 类似于 'else',没有进一步的 'if'
  // ...
  break;
}

如果评估的结果与某个标签匹配,JavaScript 会执行以下语句,直到遇到下一个 break 或者 switch 语句的末尾。如果没有标签匹配,执行将继续到 default 标签,或者(如果没有 default)则会跳过整个 switch 语句。

标签可以是文字或表达式;例如,case (2 + 1).toString(): 也是允许的。

一旦遇到 break 语句,switch 的执行就会终止。通常它会出现在每个 case 语句的末尾,以防止执行后续 case 的代码。但如果你有意图执行多个 case 的代码,可以省略 break。在以下示例中,当 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) { // 在此示例中是一个常量值
case (i < 10):
  alert("one digit");
  break;
case (i >= 10 && i < 100):
  alert("two digits");
  break;
default:
  // ...
  break;
}

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

try / catch / finally

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

try {
  // 可能会出错的关键代码块
} catch (err) {
  // 处理可能错误的代码块。通常不会执行。
} finally {
  // 无论如何都会执行的代码块
}
"use strict";

const x = 15;
let average;
try {
  // 关键代码块
  x = x + 5;
  average = x / 0;
  alert("The average is: " + average);
} catch (err) {
  // 处理可能发生的错误
  alert("Something strange occurs. The error is: " + err);
} finally {
  // 无论如何都会执行的代码
  alert("End of program.");
}

如果在关键代码块中的某个语句抛出运行时错误,则其余语句将不会执行。相反,执行会跳转到 catch 块。最后,finally 块会被执行。

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

throw

在上面的示例中,JavaScript 引擎会自动抛出异常。在其他情况下,JavaScript 引擎会以某种方式处理错误,但你可能希望看到不同的处理方式。例如,在除零错误的情况下,JavaScript 引擎不会抛出错误,而是将结果设置为 Infinity,然后跳到下一条语句。如果你想要不同的行为,你可以在自己的程序中创建并抛出异常。

"use strict";

const x = 15;
let average;
try {
  // 关键代码块
  average = x / 0;
  // 或者:const z = "abc"; average = z / 0;
  if (average === Infinity || Number.isNaN(average)) {
    // 抛出自定义异常
    throw "Error during division. The result is: " + average;
  }
  alert("The average is: " + average);
} catch (err) {
  // 处理可能的错误
  alert("Something strange occurs. The error is: " + err);
} finally {
  // 无论如何都会执行的代码
  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.";
  // 脚本会在此消息处终止(这不是一个函数)
}
alert("Next year you will be " + (age + 1));
最后修改: 2025年01月13日 星期一 15:04