在程式碼中做出決策——條件語句

在任何程式語言中,程式碼都需要根據不同的輸入做出決策並執行相應的操作。例如,在遊戲中,如果玩家的生命值為 0,那麼遊戲就結束了。在天氣應用中,如果在早上檢視,則顯示日出影像;如果在夜間,則顯示星星和月亮。在本文中,我們將探討 JavaScript 中所謂的條件語句是如何工作的。

預備知識 瞭解 HTMLCSS 基礎,熟悉前面課程中介紹的 JavaScript 基礎。
學習成果
  • 瞭解什麼是條件語句——一種根據測試結果執行不同程式碼路徑的程式碼結構。
  • 使用 if/else/else if 實現條件。
  • 使用比較運算子建立測試。
  • 在測試中實現 AND、OR 和 NOT 邏輯。
  • Switch 語句。
  • 三元運算子。

你可以在一個條件下完成!

人類(和其他動物)一直在做出影響他們生活的決定,從小到大(“我應該吃一塊餅乾還是兩塊?”)到大(“我應該留在我的祖國並在家裡的農場工作,還是應該搬到美國學習天體物理學?”)

條件語句允許我們在 JavaScript 中表示這種決策過程,從必須做出的選擇(例如,“一塊餅乾還是兩塊”),到這些選擇的最終結果(例如,“吃了一塊餅乾”的結果可能是“仍然感到飢餓”,“吃了兩塊餅乾”的結果可能是“感到飽了,但媽媽因為我吃光了餅乾而責罵我”)。

A cartoon character resembling a person holding a cookie jar labeled 'Cookies'. There is a question mark above the head of the character. There are two speech bubbles. The left speech bubble has one cookie. The right speech bubble has two cookies. Together it implies the character is trying to decide if it wants to one cookie or two cookies.

if...else 語句

讓我們來看看 JavaScript 中最常見的條件語句型別——簡單的 if...else 語句

基本的 if...else 語法

基本的 if...else 語法如下所示

js
if (condition) {
  /* code to run if condition is true */
} else {
  /* run some other code instead */
}

這裡我們有

  1. 關鍵字 if 後跟一些括號。
  2. 一個要測試的條件,放在括號內(通常是“這個值是否比另一個值大?”或“這個值是否存在?”)。該條件使用我們之前在模組中討論過的比較運算子,並返回 truefalse
  3. 一對花括號,其中包含一些程式碼——這可以是任何我們喜歡的程式碼,並且只有在條件返回 true 時才會執行。
  4. 關鍵字 else
  5. 另一對花括號,其中包含更多程式碼——這可以是任何我們喜歡的程式碼,並且只有在條件不為 true 時才會執行——換句話說,條件為 false

這段程式碼非常易讀——它表示“如果 條件 返回 true,則執行程式碼 A,否則 執行程式碼 B”。

你應該注意,你不必包含 else 和第二個花括號塊——以下也是完全合法的程式碼

js
if (condition) {
  /* code to run if condition is true */
}

/* run some other code */

但是,在這裡你需要小心——在這種情況下,第二個程式碼塊不受條件語句控制,所以它總是執行,無論條件返回 true 還是 false。這不一定是壞事,但這可能不是你想要的——通常你希望執行一個程式碼塊另一個,而不是兩者都執行。

最後一點,雖然不推薦,但你有時可能會看到沒有花括號的 if...else 語句

js
if (condition) doSomething();
else doSomethingElse();

這種語法是完全有效的,但是如果你使用花括號來界定程式碼塊,並使用多行和縮排,程式碼會更容易理解。

一個真實示例

為了更好地理解這種語法,讓我們考慮一個真實的例子。想象一個孩子被他們的母親或父親要求幫忙做家務。父母可能會說:“嘿,甜心!如果你幫我購物,我會給你一些額外的零用錢,這樣你就能買得起你想要的玩具了。”在 JavaScript 中,我們可以這樣表示:

js
let shoppingDone = false;
let childAllowance;

if (shoppingDone === true) {
  childAllowance = 10;
} else {
  childAllowance = 5;
}

如所示,這段程式碼總是導致 shoppingDone 變數返回 false,這意味著我們可憐的孩子會失望。這將由我們來提供一種機制,讓父母在孩子購物後將 shoppingDone 變數設定為 true

注意: 你可以在 GitHub 上檢視此示例的更完整版本(也可以檢視其即時執行)。

else if

上一個示例為我們提供了兩種選擇或結果——但是如果我們想要兩種以上呢?

有一種方法可以將額外的選擇/結果連結到你的 if...else——使用 else if。每個額外的選擇都需要一個額外的塊放在 if () { }else { } 之間——請看下面的更復雜的示例,它可能是一個簡單的天氣預報應用程式的一部分:

html
<label for="weather">Select the weather type today: </label>
<select id="weather">
  <option value="">--Make a choice--</option>
  <option value="sunny">Sunny</option>
  <option value="rainy">Rainy</option>
  <option value="snowing">Snowing</option>
  <option value="overcast">Overcast</option>
</select>

<p></p>
js
const select = document.querySelector("select");
const para = document.querySelector("p");

select.addEventListener("change", setWeather);

function setWeather() {
  const choice = select.value;

  if (choice === "sunny") {
    para.textContent =
      "It is nice and sunny outside today. Wear shorts! Go to the beach, or the park, and get an ice cream.";
  } else if (choice === "rainy") {
    para.textContent =
      "Rain is falling outside; take a rain coat and an umbrella, and don't stay out for too long.";
  } else if (choice === "snowing") {
    para.textContent =
      "The snow is coming down — it is freezing! Best to stay in with a cup of hot chocolate, or go build a snowman.";
  } else if (choice === "overcast") {
    para.textContent =
      "It isn't raining, but the sky is grey and gloomy; it could turn any minute, so take a rain coat just in case.";
  } else {
    para.textContent = "";
  }
}
  1. 這裡我們有一個 HTML <select> 元素,允許我們做出不同的天氣選擇,以及一個簡單的段落。
  2. 在 JavaScript 中,我們儲存了對 <select><p> 元素的引用,並向 <select> 元素添加了一個事件監聽器,以便當其值更改時,setWeather() 函式會執行。
  3. 當此函式執行時,我們首先將一個名為 choice 的變數設定為 <select> 元素中當前選定的值。然後,我們使用條件語句根據 choice 的值在段落中顯示不同的文字。請注意,除了第一個條件在 if () { } 塊中測試之外,所有條件都在 else if () { } 塊中進行測試。
  4. else { } 塊中的最後一個選擇基本上是一個“最後手段”選項——如果所有條件都不為 true,其中的程式碼將執行。在這種情況下,它用於清空段落中的文字,例如,如果使用者決定重新選擇開頭顯示的“--Make a choice--”佔位符選項。

注意: 你也可以在 GitHub 上找到此示例(也可在此處檢視其即時執行)。

關於比較運算子的說明

比較運算子用於測試條件語句中的條件。我們首先在 JavaScript 中的基本數學——數字和運算子一文中回顧了比較運算子。我們的選擇有:

  • ===!== — 測試一個值是否與另一個值相同,或不相同。
  • <> — 測試一個值是否小於或大於另一個值。
  • <=>= — 測試一個值是否小於或等於,或大於或等於另一個值。

我們特別提到了布林值(true/false)的測試,以及你將反覆遇到的一種常見模式。任何不是 falseundefinednull0NaN 或空字串('')的值,在作為條件語句測試時實際上都返回 true,因此你可以單獨使用變數名來測試它是否為 true,甚至測試它是否存在(即它不是未定義的)。例如:

js
let cheese = "Cheddar";

if (cheese) {
  console.log("Yay! Cheese available for making cheese on toast.");
} else {
  console.log("No cheese on toast for you today.");
}

回到我們之前關於孩子為父母做家務的例子,你可以這樣寫

js
let shoppingDone = false;
let childAllowance;

// We don't need to explicitly specify 'shoppingDone === true'
if (shoppingDone) {
  childAllowance = 10;
} else {
  childAllowance = 5;
}

巢狀 if...else

將一個 if...else 語句巢狀在另一個語句中是完全可以的——即巢狀它們。例如,我們可以更新我們的天氣預報應用程式,根據溫度顯示一組更進一步的選擇:

js
if (choice === "sunny") {
  if (temperature < 86) {
    para.textContent = `It is ${temperature} degrees outside — nice and sunny. Let's go out to the beach, or the park, and get an ice cream.`;
  } else if (temperature >= 86) {
    para.textContent = `It is ${temperature} degrees outside — REALLY HOT! If you want to go outside, make sure to put some sunscreen on.`;
  }
}

儘管所有程式碼協同工作,但每個 if...else 語句都完全獨立於另一個語句。

邏輯運算子:AND、OR 和 NOT

如果你想測試多個條件而不想編寫巢狀的 if...else 語句,邏輯運算子可以幫助你。當在條件中使用時,前兩個運算子的作用如下:

  • && — AND;允許你將兩個或更多表示式連結在一起,以便所有表示式都必須單獨評估為 true,整個表示式才返回 true
  • || — OR;允許你將兩個或更多表示式連結在一起,以便其中一個或多個表示式必須單獨評估為 true,整個表示式才返回 true

舉個 AND 的例子,前面的程式碼片段可以改寫成這樣

js
if (choice === "sunny" && temperature < 86) {
  para.textContent = `It is ${temperature} degrees outside — nice and sunny. Let's go out to the beach, or the park, and get an ice cream.`;
} else if (choice === "sunny" && temperature >= 86) {
  para.textContent = `It is ${temperature} degrees outside — REALLY HOT! If you want to go outside, make sure to put some sunscreen on.`;
}

所以,例如,第一個程式碼塊只會在 choice === 'sunny' 並且 temperature < 86 都返回 true 時執行。

我們來看一個快速的 OR 示例

js
if (iceCreamVanOutside || houseStatus === "on fire") {
  console.log("You should leave the house quickly.");
} else {
  console.log("Probably should just stay in then.");
}

最後一種邏輯運算子是 NOT,用 ! 運算子表示,可以用於否定一個表示式。讓我們在上例中將其與 OR 結合使用

js
if (!(iceCreamVanOutside || houseStatus === "on fire")) {
  console.log("Probably should just stay in then.");
} else {
  console.log("You should leave the house quickly.");
}

在這段程式碼中,如果 OR 語句返回 true,NOT 運算子將否定它,使得整個表示式返回 false

你可以根據需要組合任意數量的邏輯語句,無論採用何種結構。以下示例僅當兩個 OR 語句都返回 true 時才執行內部程式碼,這意味著整個 AND 語句將返回 true

js
if ((x === 5 || y > 3 || z <= 10) && (loggedIn || userName === "Steve")) {
  // run the code
}

在條件語句中使用邏輯或運算子時,一個常見的錯誤是嘗試只宣告一次要檢查其值的變數,然後給出它可能返回 true 的值列表,並用 || (OR) 運算子分隔。例如:

js
if (x === 5 || 7 || 10 || 20) {
  // run my code
}

在這種情況下,if () 內的條件將始終評估為 true,因為 7(或任何其他非零值)始終評估為 true。這個條件實際上是說“如果 x 等於 5,或者 7 是 true——它總是 true”。這在邏輯上不是我們想要的!要使其正常工作,你必須在每個 OR 運算子的兩側指定一個完整的測試

js
if (x === 5 || x === 7 || x === 10 || x === 20) {
  // run my code
}

switch 語句

if...else 語句能夠很好地實現條件程式碼,但它們並非沒有缺點。它們主要適用於只有幾個選擇,每個選擇都需要執行相當多的程式碼,並且/或者條件很複雜(例如,有多個邏輯運算子)的情況。對於你只想根據條件將變數設定為某個選擇的值或打印出特定語句的情況,語法可能有點笨重,特別是當你有大量選擇時。

在這種情況下,switch 語句就是你的朋友——它們將單個表示式/值作為輸入,然後遍歷幾個選擇,直到找到與該值匹配的選擇,並執行與之相關的相應程式碼。這裡有一些虛擬碼,給你一個概念:

js
switch (expression) {
  case choice1:
    // run this code
    break;

  case choice2:
    // run this code instead
    break;

  // include as many cases as you like

  default:
    // actually, just run this code
    break;
}

這裡我們有

  1. 關鍵字 switch,後跟一組括號。
  2. 括號內的表示式或值。
  3. 關鍵字 case,後跟表示式/值可能成為的選擇,再後跟一個冒號。
  4. 如果選擇與表示式匹配,則執行一些程式碼。
  5. 一個 break 語句,後跟一個分號。如果前一個選擇與表示式/值匹配,瀏覽器將在此處停止執行程式碼塊,並繼續執行 switch 語句下方出現的任何程式碼。
  6. 儘可能多的其他情況(第 3-5 點)。
  7. 關鍵字 default,後面跟著與其中一個 case(第 3-5 點)完全相同的程式碼模式,只是 default 後面沒有選擇,而且你不需要 break 語句,因為在這個塊之後無論如何都沒有要執行的程式碼。這是在沒有任何選擇匹配時的預設選項。

注意: 你不必包含 default 部分——如果表示式不可能最終等於未知值,你可以安全地省略它。但是,如果存在這種可能性,你需要包含它來處理未知情況。

一個 switch 示例

讓我們看一個真實的例子——我們將重寫我們的天氣預報應用程式,轉而使用 switch 語句

html
<label for="weather">Select the weather type today: </label>
<select id="weather">
  <option value="">--Make a choice--</option>
  <option value="sunny">Sunny</option>
  <option value="rainy">Rainy</option>
  <option value="snowing">Snowing</option>
  <option value="overcast">Overcast</option>
</select>

<p></p>
js
const select = document.querySelector("select");
const para = document.querySelector("p");

select.addEventListener("change", setWeather);

function setWeather() {
  const choice = select.value;

  switch (choice) {
    case "sunny":
      para.textContent =
        "It is nice and sunny outside today. Wear shorts! Go to the beach, or the park, and get an ice cream.";
      break;
    case "rainy":
      para.textContent =
        "Rain is falling outside; take a rain coat and an umbrella, and don't stay out for too long.";
      break;
    case "snowing":
      para.textContent =
        "The snow is coming down — it is freezing! Best to stay in with a cup of hot chocolate, or go build a snowman.";
      break;
    case "overcast":
      para.textContent =
        "It isn't raining, but the sky is grey and gloomy; it could turn any minute, so take a rain coat just in case.";
      break;
    default:
      para.textContent = "";
  }
}

注意: 你也可以在 GitHub 上找到此示例(在此處檢視其即時執行)。

三元運算子

在我們讓你練習一些示例之前,我們想向你介紹最後一個語法。 三元運算子或條件運算子是一種測試條件並返回一個值/表示式(如果為 true)或另一個值/表示式(如果為 false)的小段語法——這在某些情況下可能很有用,並且如果透過 true/false 條件在兩個選擇之間進行選擇,它比 if...else 塊佔用的程式碼要少得多。虛擬碼如下所示

js
condition ? run this code : run this code instead

我們來看一個例子

js
const greeting = isBirthday
  ? "Happy birthday Mrs. Smith — we hope you have a great day!"
  : "Good morning Mrs. Smith.";

這裡我們有一個名為 isBirthday 的變數——如果它為 true,我們向客人傳送生日快樂的訊息;如果不是,我們給她標準的日常問候。

三元運算子示例

三元運算子不僅用於設定變數值;你還可以執行函式或程式碼行——任何你喜歡的。以下即時示例展示了一個簡單的主題選擇器,其中使用三元運算子應用網站的樣式。

html
<label for="theme">Select theme: </label>
<select id="theme">
  <option value="white">White</option>
  <option value="black">Black</option>
</select>

<h1>This is my website</h1>
js
const select = document.querySelector("select");
const html = document.querySelector("html");
document.body.style.padding = "10px";

function update(bgColor, textColor) {
  html.style.backgroundColor = bgColor;
  html.style.color = textColor;
}

select.addEventListener("change", () =>
  select.value === "black"
    ? update("black", "white")
    : update("white", "black"),
);

這裡我們有一個 <select> 元素用於選擇主題(黑色或白色),以及一個簡單的 h1 用於顯示網站標題。我們還有一個名為 update() 的函式,它接受兩種顏色作為引數(輸入)。網站的背景顏色設定為提供的第一種顏色,文字顏色設定為提供的第二種顏色。

最後,我們還有一個 onchange 事件監聽器,用於執行一個包含三元運算子的函式。它以一個測試條件開始——select.value === 'black'。如果它返回 true,我們使用黑色和白色引數執行 update() 函式,這意味著我們最終得到黑色的背景顏色和白色的文字顏色。如果它返回 false,我們使用白色和黑色引數執行 update() 函式,這意味著網站顏色會反轉。

注意: 你也可以在 GitHub 上找到此示例(在此處檢視其即時執行)。

實現一個基本日曆

在這個例子中,你將幫助我們完成一個基本的日曆應用程式。在你的程式碼中,你將擁有

  • 一個 <select> 元素,允許使用者在不同的月份之間進行選擇。
  • 一個 change 事件處理程式,用於檢測 <select> 選單中選定的值何時更改。
  • 一個名為 createCalendar() 的函式,它繪製日曆並在 h1 元素中顯示正確的月份。

完成示例

  1. 單擊下面程式碼塊中的**“播放”**以在 MDN Playground 中編輯示例。
  2. createCalendar() 函式中,緊跟在 // ADD CONDITIONAL HERE 註釋下方編寫一個條件語句。它應該
    1. 檢視選定的月份(儲存在 choice 變數中。這將是值更改後 <select> 元素的值,例如“January”)。
    2. days 變數賦值為所選月份的天數。為此,你需要查閱一年中每個月份的天數。在此示例中,你可以忽略閏年。

提示

  • 建議您使用邏輯 OR 將多個月份分組為一個條件;它們中的許多月份天數相同。
  • 思考哪個月的天數最常見,並將其作為預設值。

如果你犯了錯誤,可以使用 MDN Playground 中的 _重置_ 按鈕清除你的工作。如果你實在卡住了,可以在即時輸出下方檢視解決方案。

js
const select = document.querySelector("select");
const list = document.querySelector("ul");
const h1 = document.querySelector("h1");

select.addEventListener("change", () => {
  const choice = select.value;
  createCalendar(choice);
});

function createCalendar(month) {
  let days = 31;

  // ADD CONDITIONAL HERE

  list.textContent = "";
  h1.textContent = month;
  for (let i = 1; i <= days; i++) {
    const listItem = document.createElement("li");
    listItem.textContent = i;
    list.appendChild(listItem);
  }
}

select.value = "January";
createCalendar("January");
點選此處顯示解決方案

你完成的 JavaScript 應該如下所示

js
const select = document.querySelector("select");
const list = document.querySelector("ul");
const h1 = document.querySelector("h1");

select.addEventListener("change", () => {
  const choice = select.value;
  createCalendar(choice);
});

function createCalendar(month) {
  let days = 31;

  if (month === "February") {
    days = 28;
  } else if (
    month === "April" ||
    month === "June" ||
    month === "September" ||
    month === "November"
  ) {
    days = 30;
  }

  list.textContent = "";
  h1.textContent = month;
  for (let i = 1; i <= days; i++) {
    const listItem = document.createElement("li");
    listItem.textContent = i;
    list.appendChild(listItem);
  }
}

select.value = "January";
createCalendar("January");

新增更多顏色選擇

在此示例中,你將使用我們前面看到的三元運算子示例,並將三元運算子轉換為 switch 語句,以允許我們為網站應用更多選擇。檢視 <select> — 這次你會看到它不是隻有兩個主題選項,而是五個。

完成示例

  1. 單擊下面程式碼塊中的**“播放”**以在 MDN Playground 中編輯示例。
  2. // ADD SWITCH STATEMENT 註釋下方新增一個 switch 語句
    1. 它應該接受 choice 變數作為其輸入表示式。
    2. 對於每個 case,選擇應等於可選的 <option> 值之一,即 whiteblackpurpleyellowpsychedelic。請注意,選項值是小寫的,而選項標籤(如即時輸出中所示)是首字母大寫的。您應該在程式碼中使用小寫值。
    3. 對於每種情況,都應執行 update() 函式,並傳入兩個顏色值,第一個用於背景顏色,第二個用於文字顏色。請記住,顏色值是字串,因此需要用引號括起來。

如果你犯了錯誤,可以使用 MDN Playground 中的 _重置_ 按鈕清除你的工作。如果你實在卡住了,可以在即時輸出下方檢視解決方案。

js
const select = document.querySelector("select");
const html = document.querySelector("html");

select.addEventListener("change", () => {
  const choice = select.value;

  // ADD SWITCH STATEMENT
});

function update(bgColor, textColor) {
  html.style.backgroundColor = bgColor;
  html.style.color = textColor;
}
點選此處顯示解決方案

你完成的 JavaScript 應該如下所示

js
const select = document.querySelector("select");
const html = document.querySelector("html");

select.addEventListener("change", () => {
  const choice = select.value;

  switch (choice) {
    case "black":
      update("black", "white");
      break;
    case "white":
      update("white", "black");
      break;
    case "purple":
      update("purple", "white");
      break;
    case "yellow":
      update("yellow", "purple");
      break;
    case "psychedelic":
      update("lime", "purple");
      break;
  }
});

function update(bgColor, textColor) {
  html.style.backgroundColor = bgColor;
  html.style.color = textColor;
}

總結

目前,關於 JavaScript 中的條件結構,你真正需要知道的就是這些了!在下一篇文章中,我們將為你提供一些測試,你可以用它們來檢查你對這些資訊的理解和記憶程度。

另見