JavaScript/控制結構
大多數程式語言都由“積木”組成,例如標記(關鍵字、變數、運算子等)、表示式(例如 myArray.length + 1)、語句(用 ; 分隔)、塊 {...}、函式和模組。乍一看,程式的執行遵循語句的順序,從上到下。但在幾乎所有情況下,程式都需要不按語句的嚴格順序執行。相反,某些部分必須僅在滿足特定條件時才執行,而其他部分將被省略並在不同的條件下執行。或者,可能需要某些部分重複執行。其他部分可能會並行執行,並在稍後同步。或者,不同模組的函式必須計算出值,然後才能執行下一個語句。
在這個“語言積木”的層次結構中,術語 **塊** 對於理解程式流程至關重要。在 JavaScript 中,塊是零個或多個語句(或較小的塊)的序列,這些語句被大括號包圍 { // 零個或多個語句 }。我們在這裡討論的語言結構會呼叫或重複塊。
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 {
// 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));
迴圈和迭代是其他情況,在這些情況下,語句的順序流程由周圍的語言結構進行操作。這將在下一頁中進行描述。