在代码中做出决定 - 条件

在任何编程语言中,代码都需要根据不同的输入做出相应的决策并执行操作。例如,在游戏中,如果玩家的生命数为 0,则游戏结束。在天气应用中,如果在早上查看,则显示日出图形;如果是夜间,则显示星星和月亮。在本文中,我们将探讨所谓的条件语句在 JavaScript 中的工作原理。

¥In any programming language, the code needs to make decisions and carry out actions accordingly depending on different inputs. For example, in a game, if the player's number of lives is 0, then it's game over. In a weather app, if it is being looked at in the morning, show a sunrise graphic; show stars and a moon if it is nighttime. In this article, we'll explore how so-called conditional statements work in JavaScript.

先决条件: 对 HTML、CSS 和 JavaScript 第一步 有基本了解。
目标: 了解如何在 JavaScript 中使用条件结构。

只要有一个条件就可以拥有!

¥You can have it on one condition!

人类(和其他动物)无时无刻不在做出影响他们生活的决定,从小("我应该吃一块还是两块饼干?")到大("我应该留在祖国并在父亲的农场工作,还是应该搬到美国学习天体物理学?")

¥Human beings (and other animals) make decisions all the time that affect their lives, from small ("should I eat one cookie or two?") to large ("should I stay in my home country and work on my father's farm, or should I move to America and study astrophysics?")

条件语句允许我们在 JavaScript 中表示这样的决策,从必须做出的选择(例如,"一两块饼干")到这些选择的结果(也许 "吃了一块饼干" 的结果可能是 "还是觉得饿","吃了两块饼干" 的结果可能是 "感觉很饱,但妈妈责备我吃掉了所有的饼干"。)

¥Conditional statements allow us to represent such decision making in JavaScript, from the choice that must be made (for example, "one cookie or two"), to the resulting outcome of those choices (perhaps the outcome of "ate one cookie" might be "still felt hungry", and the outcome of "ate two cookies" might be "felt full, but mom scolded me for eating all the cookies".)

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

¥if...else statements

让我们看看迄今为止你将在 JavaScript 中使用的最常见的条件语句类型 - 简单的 if...else 声明

¥Let's look at by far the most common type of conditional statement you'll use in JavaScript — the humble if...else statement.

基本 if...else 语法

¥Basic if...else syntax

基本 if...else 语法如下所示:

¥Basic if...else syntax looks like this:

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

这里我们有:

¥Here we've got:

  1. 关键字 if 后跟一些括号。
  2. 要测试的条件,放在括号内(通常为 "这个值比另一个值大吗?" 或 "这个值存在吗?")。该条件利用我们在上一个模块中讨论的 比较运算符 并返回 truefalse
  3. 一组大括号,里面有一些代码 - 这可以是我们喜欢的任何代码,并且仅在条件返回 true 时运行。
  4. 关键字 else
  5. 另一组大括号,里面有更多代码 - 这可以是我们喜欢的任何代码,并且仅在条件不是 true 时运行 - 或者换句话说,条件是 false

这段代码非常适合人类阅读 - 它表示“如果条件返回 true,则运行代码 A,否则运行代码 B”

¥This code is pretty human-readable — it is saying "if the condition returns true, run code A, else run code B"

你应该注意,你不必包含 else 和第二个大括号块 - 以下也是完全合法的代码:

¥You should note that you don't have to include the else and the second curly brace block — the following is also perfectly legal code:

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

/* run some other code */

但是,这里需要小心 - 在这种情况下,第二个代码块不受条件语句控制,因此它始终运行,无论条件返回 true 还是 false。这不一定是一件坏事,但它可能不是你想要的 - 通常你想要运行一个代码块或另一个,而不是两者都运行。

¥However, you need to be careful here — in this case, the second block of code is not controlled by the conditional statement, so it always runs, regardless of whether the condition returns true or false. This is not necessarily a bad thing, but it might not be what you want — often you want to run one block of code or the other, not both.

最后一点,虽然不推荐,但有时你可能会看到不带大括号的 if...else 语句:

¥As a final point, while not recommended, you may sometimes see if...else statements written without the curly braces:

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

此语法完全有效,但如果使用大括号来分隔代码块,并使用多行和缩进,则更容易理解代码。

¥This syntax is perfectly valid, but it is much easier to understand the code if you use the curly braces to delimit the blocks of code, and use multiple lines and indentation.

一个真实的例子

¥A real example

为了更好地理解这个语法,让我们考虑一个真实的例子。想象一下,一个子级的母亲或父亲请求帮助做家务。父级可能会说:“嘿,亲爱的!如果你帮我去购物,我会给你一些额外的零花钱,这样你就能买得起你想要的玩具。”在 JavaScript 中,我们可以这样表示:

¥To understand this syntax better, let's consider a real example. Imagine a child being asked for help with a chore by their mother or father. The parent might say "Hey sweetheart! If you help me by going and doing the shopping, I'll give you some extra allowance so you can afford that toy you wanted." In JavaScript, we could represent this like so:

js
let shoppingDone = false;
let childsAllowance;

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

如图所示的这段代码总是导致 shoppingDone 变量返回 false,这对我们可怜的子级来说意味着失望。如果子级购物,我们需要为父级提供一种机制,将 shoppingDone 变量设置为 true

¥This code as shown always results in the shoppingDone variable returning false, meaning disappointment for our poor child. It'd be up to us to provide a mechanism for the parent to set the shoppingDone variable to true if the child did the shopping.

注意:你可以看到更多的 GitHub 上此示例的完整版本(也可以看到 实时运行。)

¥Note: You can see a more complete version of this example on GitHub (also see it running live.)

else if

最后一个例子为我们提供了两种选择或结果 - 但是如果我们想要两个以上怎么办?

¥The last example provided us with two choices, or outcomes — but what if we want more than two?

有一种方法可以将额外的选择/结果链接到你的 if...else - 使用 else if。每个额外的选择都需要在 if () { }else { } 之间添加一个额外的块 - 请查看以下更复杂的示例,它可能是简单天气预报应用的一部分:

¥There is a way to chain on extra choices/outcomes to your if...else — using else if. Each extra choice requires an additional block to put in between if () { } and else { } — check out the following more involved example, which could be part of a simple weather forecast application:

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 的值显示段落内的不同文本。请注意如何在 else if () { } 块中测试所有条件,除了第一个条件是在 if () { } 块中测试的。
  4. else { } 块内的最后一个选择基本上是 "最后一招" 选项 - 如果没有任何条件满足 true,则将运行其中的代码。在这种情况下,如果未选择任何内容,则它会清空段落中的文本,例如,如果用户决定重新选择开头显示的 "* 做出选择 -" 占位符选项。

注意:你也可以 在 GitHub 上找到这个示例看到它实时运行 也在那里。)

¥Note: You can also find this example on GitHub (see it running live on there also.)

关于比较运算符的注释

¥A note on comparison operators

比较运算符用于测试条件语句中的条件。我们首先在 JavaScript 中的基础数学 - 数字和运算符 文章中讨论了比较运算符。我们的选择是:

¥Comparison operators are used to test the conditions inside our conditional statements. We first looked at comparison operators back in our Basic math in JavaScript — numbers and operators article. Our choices are:

  • ===!== — 测试一个值是否与另一个值相同或不相同。
  • <> — 测试一个值是否小于或大于另一个值。
  • <=>= — 测试一个值是否小于或等于或大于或等于另一个值。

我们想特别提及测试布尔 (true/false) 值,以及你会一次又一次遇到的常见模式。任何不是 falseundefinednull0NaN 或空字符串 ('') 的值在作为条件语句测试时实际上会返回 true,因此你可以单独使用变量名称来测试它是否是 true,或者 即使它存在(也就是说,它不是未定义的。)例如:

¥We wanted to make a special mention of testing boolean (true/false) values, and a common pattern you'll come across again and again. Any value that is not false, undefined, null, 0, NaN, or an empty string ('') actually returns true when tested as a conditional statement, therefore you can use a variable name on its own to test whether it is true, or even that it exists (that is, it is not undefined.) So for example:

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.");
}

并且,回到我们之前关于子级为父级做家务的例子,你可以这样写:

¥And, returning to our previous example about the child doing a chore for their parent, you could write it like this:

js
let shoppingDone = false;
let childsAllowance;

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

嵌套 if...else

¥Nesting if...else

将一个 if...else 语句放入另一个语句中是完全可以的 - 以嵌套它们。例如,我们可以更新天气预报应用,以根据温度显示更多选择:

¥It is perfectly OK to put one if...else statement inside another one — to nest them. For example, we could update our weather forecast application to show a further set of choices depending on what the temperature is:

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 语句的工作完全独立于其他语句。

¥Even though the code all works together, each if...else statement works completely independently of the other one.

逻辑运算符:与、或、非

¥Logical operators: AND, OR and NOT

如果你想测试多个条件而不编写嵌套的 if...else 语句,逻辑运算符 可以帮助你。当在条件中使用时,前两个执行以下操作:

¥If you want to test multiple conditions without writing nested if...else statements, logical operators can help you. When used in conditions, the first two do the following:

  • && — AND;允许你将两个或多个表达式链接在一起,以便所有表达式都必须单独计算为 true,整个表达式才能返回 true
  • || — OR;允许你将两个或多个表达式链接在一起,以便其中一个或多个表达式必须单独计算为 true,整个表达式才能返回 true

为了给你提供一个 AND 示例,前面的示例片段可以重写为:

¥To give you an AND example, the previous example snippet can be rewritten to this:

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 时,第一个代码块才会运行。

¥So for example, the first code block will only be run if choice === 'sunny' and temperature < 86 return true.

让我们看一个简单的 OR 示例:

¥Let's look at a quick OR example:

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 结合起来:

¥The last type of logical operator, NOT, expressed by the ! operator, can be used to negate an expression. Let's combine it with OR in the above example:

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

¥In this snippet, if the OR statement returns true, the NOT operator will negate it so that the overall expression returns false.

你可以根据需要以任何结构将任意数量的逻辑语句组合在一起。以下示例仅当两个 OR 语句都返回 true 时才执行内部代码,这意味着整个 AND 语句将返回 true:

¥You can combine as many logical statements together as you want, in whatever structure. The following example executes the code inside only if both OR statements return true, meaning that the overall AND statement will return true:

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

在条件语句中使用逻辑 OR 运算符时的一个常见错误是尝试声明你要检查一次其值的变量,然后给出可能返回 true 的值列表,并用 || (OR) 运算符分隔。例如:

¥A common mistake when using the logical OR operator in conditional statements is to try to state the variable whose value you are checking once, and then give a list of values it could be to return true, separated by || (OR) operators. For example:

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

在这种情况下,if () 内的条件将始终评估为 true,因为 7(或任何其他非零值)始终评估为 true。这个条件实际上就是说 "如果 x 等于 5,或者 7 为真 - 它总是如此"。从逻辑上讲这不是我们想要的!为了使这项工作有效,你必须在每个 OR 运算符的任一侧指定完整的测试:

¥In this case, the condition inside if () will always evaluate to true since 7 (or any other non-zero value) always evaluates to true. This condition is actually saying "if x equals 5, or 7 is true — which it always is". This is logically not what we want! To make this work you've got to specify a complete test on either side of each OR operator:

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

switch 语句

¥switch statements

if...else 语句很好地完成了启用条件代码的工作,但它们也并非没有缺点。它们主要适用于以下情况:你有多种选择,并且每种选择都需要运行合理数量的代码,和/或条件很复杂(例如,多个逻辑运算符)。对于你只想将变量设置为某个值选择或根据条件打印出特定语句的情况,语法可能有点麻烦,特别是当你有大量选择时。

¥if...else statements do the job of enabling conditional code well, but they are not without their downsides. They are mainly good for cases where you've got a couple of choices, and each one requires a reasonable amount of code to be run, and/or the conditions are complex (for example, multiple logical operators). For cases where you just want to set a variable to a certain choice of value or print out a particular statement depending on a condition, the syntax can be a bit cumbersome, especially if you've got a large number of choices.

在这种情况下,switch 声明 是你的朋友 - 他们将单个表达式/值作为输入,然后浏览多个选择,直到找到与该值匹配的一个,并执行与之相关的相应代码。这里还有一些伪代码,可以给你一个想法:

¥In such a case, switch statements are your friend — they take a single expression/value as an input, and then look through several choices until they find one that matches that value, executing the corresponding code that goes along with it. Here's some more pseudocode, to give you an idea:

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;
}

这里我们有:

¥Here we've got:

  1. 关键字 switch,后跟一组括号。
  2. 括号内的表达式或值。
  3. 关键字 case,后跟表达式/值可能的选择,后跟冒号。
  4. 如果选择与表达式匹配,则运行一些代码。
  5. break 语句,后跟分号。如果先前的选择与表达式/值匹配,则浏览器将停止执行此处的代码块,并继续执行 switch 语句下方出现的任何代码。
  6. 其他情况(第 3-5 项)随你喜欢。
  7. 关键字 default,后跟与其中一种情况(项目符号 3-5)完全相同的代码模式,除了 default 之后没有选择,并且你不需要 break 语句,因为后面没有任何可运行的内容 无论如何,这在街区里。这是在没有任何选项匹配时运行的默认选项。

注意:你不必包含 default 部分 - 如果表达式最终不可能等于未知值,你可以安全地省略它。但是,如果有可能发生这种情况,你需要将其包含在内以处理未知情况。

¥Note: You don't have to include the default section — you can safely omit it if there is no chance that the expression could end up equaling an unknown value. If there is a chance of this, however, you need to include it to handle unknown cases.

一个开关示例

¥A switch example

让我们看一个真实的例子 - 我们将重写天气预报应用以使用 switch 语句:

¥Let's have a look at a real example — we'll rewrite our weather forecast application to use a switch statement instead:

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 上找到这个示例(也可以在此处查看 实时运行。)

¥Note: You can also find this example on GitHub (see it running live on there also.)

三元运算符

¥Ternary operator

在让你使用一些示例之前,我们想向你介绍最后一点语法。三元或条件运算符 是一小段语法,用于测试条件,如果是 true,则返回一个值/表达式,如果是 false,则返回另一个值/表达式 — 这在某些情况下很有用,并且比 if...else 块占用的代码要少得多 如果你有两个选择,可以通过 true/false 条件进行选择。伪代码如下所示:

¥There is one final bit of syntax we want to introduce you to before we get you to play with some examples. The ternary or conditional operator is a small bit of syntax that tests a condition and returns one value/expression if it is true, and another if it is false — this can be useful in some situations, and can take up a lot less code than an if...else block if you have two choices that are chosen between via a true/false condition. The pseudocode looks like this:

js
condition ? run this code : run this code instead

让我们看一个简单的例子:

¥So let's look at a simple example:

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

这里我们有一个名为 isBirthday 的变量 - 如果是 true,我们就给我们的客人一条生日快乐消息;如果没有,我们会给她标准的日常问候。

¥Here we have a variable called isBirthday — if this is true, we give our guest a happy birthday message; if not, we give her the standard daily greeting.

三元运算符示例

¥Ternary operator example

三元运算符不仅仅用于设置变量值;你还可以运行函数或代码行 - 任何你喜欢的东西。以下实例显示了一个简单的主题选择器,其中使用三元运算符应用网站的样式。

¥The ternary operator is not just for setting variable values; you can also run functions, or lines of code — anything you like. The following live example shows a simple theme chooser where the styling for the site is applied using a ternary operator.

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() 的函数,它采用两种颜色作为参数(输入)。网站的背景颜色设置为第一个提供的颜色,其文本颜色设置为第二个提供的颜色。

¥Here we've got a <select> element to choose a theme (black or white), plus a simple h1 to display a website title. We also have a function called update(), which takes two colors as parameters (inputs). The website's background color is set to the first provided color, and its text color is set to the second provided color.

最后,我们还有一个 onchange 事件监听器,用于运行包含三元运算符的函数。它以测试条件 — select.value === 'black' 开始。如果返回 true,我们将使用黑色和白色参数运行 update() 函数,这意味着我们最终会得到黑色背景颜色和白色文本颜色。如果它返回 false,我们就运行参数为白色和黑色的 update() 函数,这意味着站点颜色被反转。

¥Finally, we've also got an onchange event listener that serves to run a function containing a ternary operator. It starts with a test condition — select.value === 'black'. If this returns true, we run the update() function with parameters of black and white, meaning that we end up with a background color of black and a text color of white. If it returns false, we run the update() function with parameters of white and black, meaning that the site colors are inverted.

注意:你也可以 在 GitHub 上找到这个示例(也可以在此处查看 实时运行。)

¥Note: You can also find this example on GitHub (see it running live on there also.)

主动学习:一个简单的日历

¥Active learning: A simple calendar

在此示例中,你将帮助我们完成一个简单的日历应用。在你的代码中:

¥In this example, you are going to help us finish a simple calendar application. In the code you've got:

  • <select> 元素允许用户在不同月份之间进行选择。
  • onchange 事件处理程序,用于检测 <select> 菜单中选择的值何时发生更改。
  • 名为 createCalendar() 的函数绘制日历并在 h1 元素中显示正确的月份。

我们需要你在 onchange 处理函数内编写一个条件语句,就在 // ADD CONDITIONAL HERE 注释的下方。它应该:

¥We need you to write a conditional statement inside the onchange handler function, just below the // ADD CONDITIONAL HERE comment. It should:

  1. 查看所选月份(存储在 choice 变量中。这将是值更改后的 <select> 元素值,因此以 "一月" 为例。)
  2. 将名为 days 的变量设置为等于所选月份的天数。为此,你必须查找一年中每个月的天数。出于本示例的目的,你可以忽略闰年。

提示:

¥Hints:

  • 建议你使用逻辑“或”将多个月份组合成一个条件;其中许多人的天数相同。
  • 考虑最常见的天数,并将其用作默认值。

如果你犯了错误,你可以随时使用 "重置" 按钮重置示例。如果你确实遇到困难,请按 "显示解决方案" 查看解决方案。

¥If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.

html
<h2>Live output</h2>
<iframe id="output" width="100%" height="600px"></iframe>

<h2>Editable code</h2>
<p class="a11y-label">
  Press Esc to move focus away from the code area (Tab inserts a tab character).
</p>

<textarea id="code" class="playable-code" style="height: 400px;width: 95%">
const select = document.querySelector('select');
const list = document.querySelector('ul');
const h1 = document.querySelector('h1');

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

  // ADD CONDITIONAL HERE

  createCalendar(days, choice);
});

function createCalendar(days, choice) {
  list.innerHTML = '';
  h1.textContent = choice;
  for (let i = 1; i <= days; i++) {
    const listItem = document.createElement('li');
    listItem.textContent = i;
    list.appendChild(listItem);
  }
}

createCalendar(31, 'January');
</textarea>

<div class="playable-buttons">
  <input id="reset" type="button" value="Reset" />
  <input id="solution" type="button" value="Show solution" />
</div>
css
html {
  font-family: sans-serif;
}

h2 {
  font-size: 16px;
}

.a11y-label {
  margin: 0;
  text-align: right;
  font-size: 0.7rem;
  width: 98%;
}

body {
  margin: 10px;
  background: #f5f9fa;
}
js
const reset = document.getElementById("reset");
const solution = document.getElementById("solution");
const outputIFrame = document.querySelector("#output");
const textarea = document.getElementById("code");
const initialCode = textarea.value;
let userCode = textarea.value;

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

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

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

  createCalendar(days, choice);
});

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

createCalendar(31, "January");`;

function outputDocument(code) {
  const outputBody = `
<div class="output" style="height: 500px; overflow: auto">
  <label for="month">Select month: </label>
  <select id="month">
    <option value="January">January</option>
    <option value="February">February</option>
    <option value="March">March</option>
    <option value="April">April</option>
    <option value="May">May</option>
    <option value="June">June</option>
    <option value="July">July</option>
    <option value="August">August</option>
    <option value="September">September</option>
    <option value="October">October</option>
    <option value="November">November</option>
    <option value="December">December</option>
  </select>

  <h1></h1>

  <ul></ul>
</div>`;

  const outputStyle = `
.output * {
  box-sizing: border-box;
}

.output ul {
  padding-left: 0;
}

.output li {
  display: block;
  float: left;
  width: 25%;
  border: 2px solid white;
  padding: 5px;
  height: 40px;
  background-color: #4a2db6;
  color: white;
}
html {
  font-family: sans-serif;
}

h2 {
  font-size: 16px;
}`;
  return `
<!doctype html>
<html>
  <head>
    <style>${outputStyle}</style>
  </head>
  <body>
    ${outputBody}
    <script>${code}</script>
  </body>
</html>`;
}

function update() {
  output.setAttribute("srcdoc", outputDocument(textarea.value));
}

update();

textarea.addEventListener("input", update);

reset.addEventListener("click", () => {
  textarea.value = initialCode;
  userEntry = textarea.value;
  solution.value = "Show solution";
  update();
});

solution.addEventListener("click", () => {
  if (solution.value === "Show solution") {
    // remember the state of the user's code
    // so we can restore it
    userCode = textarea.value;
    textarea.value = solutionCode;
    solution.value = "Hide solution";
  } else {
    textarea.value = userCode;
    solution.value = "Show solution";
  }
  update();
});

// stop tab key tabbing out of textarea and
// make it write a tab at the caret position instead
textarea.onkeydown = (e) => {
  if (e.keyCode === 9) {
    e.preventDefault();
    insertAtCaret("\t");
  }

  if (e.keyCode === 27) {
    textarea.blur();
  }
};

function insertAtCaret(text) {
  const scrollPos = textarea.scrollTop;
  let caretPos = textarea.selectionStart;
  const front = textarea.value.substring(0, caretPos);
  const back = textarea.value.substring(
    textarea.selectionEnd,
    textarea.value.length,
  );

  textarea.value = front + text + back;
  caretPos += text.length;
  textarea.selectionStart = caretPos;
  textarea.selectionEnd = caretPos;
  textarea.focus();
  textarea.scrollTop = scrollPos;
}

主动学习:更多颜色选择

¥Active learning: More color choices

在这个例子中,你将采用我们之前看到的三元运算符示例,并将三元运算符转换为 switch 语句,以便我们可以将更多选择应用于简单的网站。看看 <select> — 这次你会发现它没有两个主题选项,而是五个。你需要在 // ADD SWITCH STATEMENT 注释下方添加一条 switch 语句:

¥In this example, you are going to take the ternary operator example we saw earlier and convert the ternary operator into a switch statement to allow us to apply more choices to the simple website. Look at the <select> — this time you'll see that it has not two theme options, but five. You need to add a switch statement just underneath the // ADD SWITCH STATEMENT comment:

  • 它应该接受 choice 变量作为其输入表达式。
  • 对于每种情况,选择应等于可以选择的可能 <option> 值之一,即 whiteblackpurpleyellowpsychedelic
  • 对于每种情况,都应运行 update() 函数,并传递两个颜色值,第一个用于背景颜色,第二个用于文本颜色。请记住,颜色值是字符串,因此需要将它们括在引号中。

如果你犯了错误,你可以随时使用 "重置" 按钮重置示例。如果你确实遇到困难,请按 "显示解决方案" 查看解决方案。

¥If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.

html
<h2>Live output</h2>
<div class="output" style="height: 300px;">
  <label for="theme">Select theme: </label>
  <select id="theme">
    <option value="white">White</option>
    <option value="black">Black</option>
    <option value="purple">Purple</option>
    <option value="yellow">Yellow</option>
    <option value="psychedelic">Psychedelic</option>
  </select>

  <h1>This is my website</h1>
</div>

<h2>Editable code</h2>
<p class="a11y-label">
  Press Esc to move focus away from the code area (Tab inserts a tab character).
</p>

<textarea id="code" class="playable-code" style="height: 450px;width: 95%">
const select = document.querySelector('select');
const html = document.querySelector('.output');

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

  // ADD SWITCH STATEMENT
});

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

<div class="playable-buttons">
  <input id="reset" type="button" value="Reset" />
  <input id="solution" type="button" value="Show solution" />
</div>
css
html {
  font-family: sans-serif;
}

h2 {
  font-size: 16px;
}

.a11y-label {
  margin: 0;
  text-align: right;
  font-size: 0.7rem;
  width: 98%;
}

body {
  margin: 10px;
  background: #f5f9fa;
}
js
const textarea = document.getElementById("code");
const reset = document.getElementById("reset");
const solution = document.getElementById("solution");
let code = textarea.value;
let userEntry = textarea.value;

function updateCode() {
  eval(textarea.value);
}

reset.addEventListener("click", function () {
  textarea.value = code;
  userEntry = textarea.value;
  solutionEntry = jsSolution;
  solution.value = "Show solution";
  updateCode();
});

solution.addEventListener("click", function () {
  if (solution.value === "Show solution") {
    textarea.value = solutionEntry;
    solution.value = "Hide solution";
  } else {
    textarea.value = userEntry;
    solution.value = "Show solution";
  }
  updateCode();
});

const jsSolution = `const select = document.querySelector('select');
const html = document.querySelector('.output');

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;
}`;

let solutionEntry = jsSolution;

textarea.addEventListener("input", updateCode);
window.addEventListener("load", updateCode);

// stop tab key tabbing out of textarea and
// make it write a tab at the caret position instead

textarea.onkeydown = function (e) {
  if (e.keyCode === 9) {
    e.preventDefault();
    insertAtCaret("\t");
  }

  if (e.keyCode === 27) {
    textarea.blur();
  }
};

function insertAtCaret(text) {
  const scrollPos = textarea.scrollTop;
  let caretPos = textarea.selectionStart;
  const front = textarea.value.substring(0, caretPos);
  const back = textarea.value.substring(
    textarea.selectionEnd,
    textarea.value.length,
  );

  textarea.value = front + text + back;
  caretPos += text.length;
  textarea.selectionStart = caretPos;
  textarea.selectionEnd = caretPos;
  textarea.focus();
  textarea.scrollTop = scrollPos;
}

// Update the saved userCode every time the user updates the text area code

textarea.onkeyup = function () {
  // We only want to save the state when the user code is being shown,
  // not the solution, so that solution is not saved over the user code
  if (solution.value === "Show solution") {
    userEntry = textarea.value;
  } else {
    solutionEntry = textarea.value;
  }

  updateCode();
};

测试你的技能!

¥Test your skills!

你已读完本文,但你还记得最重要的信息吗?在继续之前,你可以找到一些进一步的测试来验证你是否已保留此信息 - 请参阅 测试你的技能:条件句

¥You've reached the end of this article, but can you remember the most important information? You can find some further tests to verify that you've retained this information before you move on — see Test your skills: Conditionals.

结论

¥Conclusion

这就是你现在真正需要了解的有关 JavaScript 条件结构的全部内容!如果有什么不明白的地方,欢迎再通读一遍文章,或者 联系我们 寻求帮助。

¥And that's all you really need to know about conditional structures in JavaScript right now! If there is anything you didn't understand, feel free to read through the article again, or contact us to ask for help.

也可以看看