JavaScript编程
大多数编程语言由“构件”组成,如标记(关键字、变量、运算符等)、表达式(例如 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));