正在翻譯中。
JavaScript擁有許多陳述句,特別是控制流的陳述,你可以用這些陳述來增加你程式的互動性。這個章節將會概要介紹陳述。
JavaScript參考 中有比本章更多關於陳述句的細節. 在Javascript程式碼中,分號(;)被用來隔開陳述句.
任何JavaScript表達式也是一個陳述。 有關表達式的完整信息,請參閱表達式與運算元.
程式區塊陳述
最基本的陳述是"用於將陳述分塊"的"區塊陳述".程式區塊被以一對大括號隔離開來:
{
陳述1;
陳述2;
.
.
.
陳述n;
}
範例
區塊陳述經常被用於控制流陳述(例如:if, for, while).
while (x < 10) {
x++;
}
在這裏, { x++; }是區塊陳述.
重要: JavaScript 在 ECMAScript2015 以前的版本並沒有區塊範圍的概念. 在區塊中的變數有效範圍是包含該區塊的函式或者是執行檔,並且在區塊外也可使用它們.換句話說,區塊並不定義了範圍.Javascript中的"獨立"區塊將會產生與C和Java中不同的效果 .舉例來說:
var x = 1;
{
var x = 2;
}
console.log(x); // 輸出 2
這裏輸出了2是因為區塊中變數"var x"陳述擁有與區塊外的"var x"相同的有效範圍.在 C o或 Java, 相同的程式碼將會輸出1 .
從 ECMAScript2015 版本起, 使用let定義的變數範圍將被限制於區塊內.
條件陳述句
條件陳述句是一些在指定條件爲真下將被執行的指令. JavaScript支援兩種條件陳述: if...else 和 switch.
if...else 陳述
if陳述將在"邏輯判斷爲真"下執行接下來的一個陳述.選擇性的else陳述將會在"邏輯判斷爲否"時被執行. if陳述的用法看起來如下:
if (指定條件) {
陳述句1;
} else {
陳述句2;
}
指定條件可以是任何會回傳true或false的表達式。參見 布爾值(Boolean) 來進一步瞭解哪些表達式會回傳 true 及 false。假如指定條件爲 true,陳述句 1 會被執行;否則,陳述句2 會被執行。陳述句1 及陳述句 2 可以是任何陳述,包含巢狀 if 陳述。
你也可以藉由 else if 來使用複合的陳述句來測試多種不同的條件,如下:
if (指定條件1) {
陳述句1;
} else if (指定條件2) {
陳述句2;
} else if (指定條件n) {
陳述句n;
} else {
最後陳述句;
}
在多個條件中,只有第一個條件爲true的陳述會被執行.若要執行多個陳述,可以將陳述包在同一個程式區塊中({ ... }) . 通常來說,使用區塊陳述是很好的習慣,尤其在使用巢狀if的時候:
if (指定條件) {
陳述句_1_執行_當_指定條件_爲_真;
陳述句_2_執行_當_指定條件_爲_真;
} else {
陳述句_3_執行_當_指定條件_爲_否;
陳述句_4_執行_當_指定條件_爲_否;
}
if (x = y) {
/* 描述句 */
}
如果你真的需要以賦值作爲條件表達式, 一種常見的方式是額外在賦值式外面加上一組括號. 例如:
if ((x = y)) {
/* 描述句 */
}
爲"否"的值
下列的值會被看作false
falseundefinednull0NaN- 空字串 (
"")
其他所有的值,包含所有物件,當被作為條件陳述句都會被視為True.
不要把"布林真假值"和"布林物件的真假值"弄混了. 例如:
var b = new Boolean(false); if (b) // 這會是True if (b == true) // 這會是false
範例
I在下面的範例中,函式 checkData 回傳 true 當 Text object 的長度爲三; 否則, 顯示出 alert 並回傳 false.
function checkData() {
if (document.form1.threeChar.value.length == 3) {
return true;
} else {
alert("請輸入恰好三個字元. " +
document.form1.threeChar.value + " is not valid.");
return false;
}
}
switch 陳述
switch 陳述允許程式依表達式的不同值來選擇不同標籤. 假如表達式和標籤匹配,程式會執行標籤對應的陳述.範例如下:
switch (表達式) {
case 標籤1:
陳述句1
[break;]
case 標籤2:
陳述句2
[break;]
...
default:
陳述句
[break;]
}
程序首先尋找一個標籤與expression的值匹配的case子句,然後將控制權轉移給該子句,執行與其相關的陳述句。 如果沒有找到匹配的標籤,程序將查找default子句(選擇性),如果找到,則將控制權轉移到該子句,執行關聯的陳述句。 如果沒有找到default子句,程序繼續在switch結束後的語句執行。 按照慣例,默認子句是最後一個子句,但並不硬性規定。
與每個case子句相關聯的break陳述句(選擇性)確保程序在發現匹配的陳述句之後退出switch,並在switch後的陳述句中繼續執行。 如果省略break,程序將繼續在switch陳述中的下一個陳述句執行。
範例
在下面範例中,如果變數fruittype為“Bananas”,程序將與“Bananas”匹配並執行相關語句。 當遇到break時,程序離開switch並執行switch後的陳述句。 如果省略break,也將執行case “Cherries”的陳述句。
switch (fruittype) {
case "Oranges":
console.log("Oranges are $0.59 a pound.");
break;
case "Apples":
console.log("Apples are $0.32 a pound.");
break;
case "Bananas":
console.log("Bananas are $0.48 a pound.");
break;
case "Cherries":
console.log("Cherries are $3.00 a pound.");
break;
case "Mangoes":
console.log("Mangoes are $0.56 a pound.");
break;
case "Papayas":
console.log("Mangoes and papayas are $2.79 a pound.");
break;
default:
console.log("Sorry, we are out of " + fruittype + ".");
}
console.log("Is there anything else you'd like?");
例外處理陳述
你可以用以 throw 陳述丟出例外,並以 try...catch 陳述處理之.
例外的形態
任何物件(object)都可以在JavaScript中被拋出。 然而,並非所有拋出的物件都相同。 雖然將數字或字串作為錯誤物件使用是相當常見的,但使用為此目的專門創造的一種例外物件類型通常更有效:
throw 陳述
使用throw語句拋出例外。當拋出例外時,你要指定包含在要拋出物件中的值:
throw expression;
您可以拋出任何表達式,而不僅僅是特定類型的表達式。 以下的程式碼會拋出一些不同類型的例外:
throw "Error2"; // 字串形態
throw 42; // 數字形態
throw true; // True/False
throw {toString: function() { return "我是物件!"; } };
// 創建類型爲 UserException 的物件
function UserException(message) {
this.message = message;
this.name = "UserException";
}
// 讓例外轉換成整齊的字串當它被當作字串使用時
// (舉例來說:於 error console)
UserException.prototype.toString = function() {
return this.name + ': "' + this.message + '"';
}
// 創建一個物件的實例並丟出它
throw new UserException("Value too high");
try...catch 陳述
try ... catch語句標記了一組要嘗試的陳述句,並在拋出例外時指定一個或多個響應。 如果例外被拋出,try ... catch語句捕獲它。
try ... catch語句包括一個try塊,它包含一個或多個陳述句,零個或多個catch塊,包含在try塊中拋出例外時該做什麼的陳述句。 也就是說,你希望try塊成功,如果它不成功,你希望控制權傳遞給catch塊。 如果try塊內的任何語句(或在try塊內調用的函數中)拋出例外,則控制立即切換到catch塊。 如果在try塊中沒有拋出例外,則跳過catch塊。 finally塊在try和catch塊執行後執行,但在try ... catch陳述句之前的語句之前執行。
以下的範例使用try ... catch陳述句。該範例調用基於傳遞給函數的值並從陣列中檢索月份名稱的函數。如果值不對應於月份數(1-12),則會拋出一個例外,其值為“InvalidMonthNo”,並且catch塊中的陳述句將monthName變數設置為unknown。
function getMonthName(mo) {
mo = mo - 1; // Adjust month number for array index (1 = Jan, 12 = Dec)
var months = ["Jan","Feb","Mar","Apr","May","Jun","Jul",
"Aug","Sep","Oct","Nov","Dec"];
if (months[mo]) {
return months[mo];
} else {
throw "InvalidMonthNo"; //throw 關鍵字在這裏被使用
}
}
try { // statements to try
monthName = getMonthName(myMonth); // 函式可以丟出例外
}
catch (e) {
monthName = "unknown";
logMyErrors(e); // 將例外傳至例外處理機制
}
catch 區塊
你可以使用 catch 區塊來處理 try 區塊可能丟出的例外。
catch (catchID) {
陳述句
}
catch塊指定用來保存throw語句所丟出的值的標識符(前面語法中的catchID) 您可以使用此標識符獲取有關被拋出的例外的信息。 JavaScript在進入catch塊時創建此標識符; 標識符僅持續catch塊的持續時間; 在catch塊完成執行後,標識符不再可用。
例如,下列的程式碼中丟出了一個例外,當例外發生後,控制權被轉交給 catch 區塊。
try {
throw "myException"; // 產生例外
}
catch (e) {
// 用於處理例外的陳述句
logMyErrors(e); // 將例外物件傳給error handler
}
finally 區塊
finally區塊中包含 在try和catch塊執行之後但在try ... catch陳述之後的語句之前 執行的語句。 無論是否拋出例外,finally區塊都會執行。 如果拋出例外,則即使沒有catch區塊處理例外,finally塊中的陳述句也會執行。
您可以使用finally塊來使腳本在發生例外時正常地結束; 例如,您可能需要釋放腳本中綁定的資源。 在以下示例中,打開一個文件,然後執行使用該文件的陳述句(服務器端JavaScript允許您訪問文件)。 如果在打開文件時拋出例外,finally塊會在腳本結束之前關閉文件。
openMyFile();
try {
writeMyFile(theData); //可能產生例外
} catch(e) {
handleError(e); //處理可能發生的例外
} finally {
closeMyFile(); //總是在try結束後關閉檔案
}
如果finally區塊有返回值,那麼該值將成為整個try-catch-finally過程的返回值,而捨棄try和catch塊中的任何返回語句:
function f() {
try {
console.log(0);
throw "bogus";
} catch(e) {
console.log(1);
return true; // 這個回傳會被擱置
// 直到 finally 區塊結束
console.log(2); // 不會到達這裏
} finally {
console.log(3);
return false; // 覆寫先前的 "return"
console.log(4); // 不會到達這裏
}
// "return false" 在這裏被執行
console.log(5); // 不會到達這裏
}
f(); // console 0, 1, 3; 會回傳false
finally區塊覆寫返回值也適用於在catch區塊中拋出或重新拋出的例外(即便在catch中再次丟出例外,catch所屬的finally區塊還是會被執行):
function f() {
try {
throw "bogus";
} catch(e) {
console.log('caught inner "bogus"');
throw e; // 此處的throw陳述將被擱置到
// finally區塊結束
} finally {
return false; // 覆寫先前的"throw"
}
// "return false" 在此被執行
}
try {
f();
} catch(e) {
// 這裏永遠不可能到達因為在f函式中catch的throw
// 被finally中的return覆寫了
console.log('caught outer "bogus"');
}
// 輸出 -> caught inner "bogus"
巢狀 try...catch 陳述
你可以使用一個或多個的 try...catch 陳述. 假如一個內層的try...catch 陳述不具有 catch 塊, 它將必須要有finally塊與及封閉的 try...catch 陳述來檢測是否有符合的例外.
使用 Error 物件
根據錯誤的類型,您可以使用“name”和“message”屬性來獲取更精確的資訊。 'name'提供了錯誤所屬的類別(class)(例如,'DOMException'或'Error'),而'message'通常提供藉由將錯誤物件轉換為字串所獲得的更簡潔的資訊。參見 巢狀 try 區塊 位於 try...catch 參考資料頁面.
假如您要丟出自定義的例外, 為了方便使用這些屬性(例如,如果你的catch區塊並不要區分你自己的例外和系統的),你可以使用Error構造子。舉例來說:
function doSomethingErrorProne () {
if (ourCodeMakesAMistake()) {
throw (new Error('The message'));
} else {
doSomethingToGetAJavascriptError();
}
}
....
try {
doSomethingErrorProne();
}
catch (e) {
console.log(e.name); // 紀錄 'Error'
console.log(e.message); // 紀錄 'The message' 或者其他 JavaScript 例外的資訊)
}
Promises容器
從 ECMAScript2015 起, JavaScript 支援 Promise 物件,允許您控制延遲和異步操作的流程。
Promise 有以下幾種狀態:
- 等待: 初始狀態,不是滿足或拒絕.
- 滿足: 操作成功.
- 拒絕: 操作失敗.
- 安定: 以上皆非的一種狀態.

使用XHR載入圖檔
這裏有個簡單的範例,使用了 Promise物件 與及 XMLHttpRequest 來載入 MDN GitHub promise-test repository中的一張圖檔. 你也可以觀看結果. 每一步都有註解來讓您慢慢理解 Promise物件與及XHR架構. 下面的版本沒有註解,但藉由觀察 Promise 物件的變動您或許可以對promise物件有所遼解:
function imgLoad(url) {
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = 'blob';
request.onload = function() {
if (request.status === 200) {
resolve(request.response);
} else {
reject(Error('Image didn\'t load successfully; error code:'
+ request.statusText));
}
};
request.onerror = function() {
reject(Error('There was a network error.'));
};
request.send();
});
}
以獲得更多資訊,查看 Promise 參照頁面.