第一次接触 JavaScript

现在你已经了解了 JavaScript 的理论以及可以用它做什么,我们将通过一个实用的教程来指导你,让你了解创建简单 JavaScript 程序的过程是什么样的。在这里,你将逐步构建一个简单的 "猜数字" 游戏。

¥Now you've learned something about the theory of JavaScript and what you can do with it, we are going to give you an idea of what the process of creating a simple JavaScript program is like, by guiding you through a practical tutorial. Here you'll build up a simple "Guess the number" game, step by step.

先决条件: 对 HTML 和 CSS 有基本的了解,对 JavaScript 有了解。
目标: 拥有编写 JavaScript 的初步经验,并至少对编写 JavaScript 程序涉及的内容有一个基本的了解。

我们想在这里设定非常明确的期望:读完本文后,你不需要学习 JavaScript,甚至不需要理解我们要求你编写的所有代码。相反,我们想让你了解 JavaScript 的功能如何协同工作,以及编写 JavaScript 的感觉。在后续文章中,你将更详细地重新审视此处显示的所有功能,因此,如果你没有立即理解所有内容,请不要担心!

¥We want to set really clear expectations here: You won't be expected to learn JavaScript by the end of this article, or even understand all the code we are asking you to write. Instead, we want to give you an idea of how JavaScript's features work together, and what writing JavaScript feels like. In subsequent articles you'll revisit all the features shown here in a lot more detail, so don't worry if you don't understand it all immediately!

注意:你在 JavaScript 中看到的许多代码功能与其他编程语言中的相同 - 函数、循环等。代码语法看起来不同,但概念仍然基本相同。

¥Note: Many of the code features you'll see in JavaScript are the same as in other programming languages — functions, loops, etc. The code syntax looks different, but the concepts are still largely the same.

像程序员一样思考

¥Thinking like a programmer

编程中最难学习的事情之一不是你需要学习的语法,而是如何应用它来解决现实世界的问题。你需要开始像程序员一样思考 - 这通常涉及查看你的程序需要做什么的描述,弄清楚实现这些事情需要哪些代码功能,以及如何让它们一起工作。

¥One of the hardest things to learn in programming is not the syntax you need to learn, but how to apply it to solve real-world problems. You need to start thinking like a programmer — this generally involves looking at descriptions of what your program needs to do, working out what code features are needed to achieve those things, and how to make them work together.

这需要艰苦的工作、编程语法的经验和实践 - 再加上一点创造力。你编写的代码越多,你就会越好。我们不能保证你将在五分钟内开发出 "程序员大脑",但我们将在整个课程中为你提供大量机会像程序员一样练习思考。

¥This requires a mixture of hard work, experience with the programming syntax, and practice — plus a bit of creativity. The more you code, the better you'll get at it. We can't promise that you'll develop "programmer brain" in five minutes, but we will give you plenty of opportunities to practice thinking like a programmer throughout the course.

考虑到这一点,让我们看一下我们将在本文中构建的示例,并回顾将其分解为具体任务的一般过程。

¥With that in mind, let's look at the example we'll be building up in this article, and review the general process of dissecting it into tangible tasks.

示例 — 猜数字游戏

¥Example — Guess the number game

在本文中,我们将向你展示如何构建下面所示的简单游戏:

¥In this article we'll show you how to build up the simple game you can see below:

尝试一下 - 在继续之前先熟悉一下游戏。

¥Have a go at playing it — familiarize yourself with the game before you move on.

假设你的老板为你提供了以下关于创建此游戏的简介:

¥Let's imagine your boss has given you the following brief for creating this game:

我希望你创建一个简单的猜数字类型的游戏。它应该选择一个 1 到 100 之间的随机数字,然后挑战玩家在 10 轮内猜测这个数字。每回合结束后,应该告诉玩家他们是对还是错,如果错了,猜测是否太低或太高。它还应该告诉玩家他们之前猜到了什么数字。一旦玩家猜对,或者用完回合,游戏就会结束。当游戏结束时,玩家应该可以选择重新开始游戏。

¥I want you to create a simple guess the number type game. It should choose a random number between 1 and 100, then challenge the player to guess the number in 10 turns. After each turn, the player should be told if they are right or wrong, and if they are wrong, whether the guess was too low or too high. It should also tell the player what numbers they previously guessed. The game will end once the player guesses correctly, or once they run out of turns. When the game ends, the player should be given an option to start playing again.

看完这个简介后,我们能做的第一件事就是开始将其分解为简单的可操作任务,尽可能以程序员的心态:

¥Upon looking at this brief, the first thing we can do is to start breaking it down into simple actionable tasks, in as much of a programmer mindset as possible:

  1. 生成 1 到 100 之间的随机数。
  2. 记录玩家所在的回合数。从 1 开始。
  3. 为玩家提供一种猜测数字的方法。
  4. 提交猜测后,首先将其记录在某处,以便用户可以看到他们之前的猜测。
  5. 接下来,检查该号码是否正确。
  6. 如果正确的话:
    1. 显示祝贺消息。
    2. 阻止玩家输入更多猜测(这会使游戏变得混乱)。
    3. 显示控制允许玩家重新开始游戏。
  7. 如果错误并且玩家左转:
    1. 告诉玩家他们错了,以及他们的猜测是否太高或太低。
    2. 让他们输入另一个猜测。
    3. 将回合数加 1。
  8. 如果错误且玩家没有剩余回合:
    1. 告诉玩家游戏结束了。
    2. 阻止玩家输入更多猜测(这会使游戏变得混乱)。
    3. 显示控制允许玩家重新开始游戏。
  9. 游戏重新启动后,请确保游戏逻辑和 UI 已完全重置,然后返回步骤 1。

现在让我们继续前进,看看如何将这些步骤转化为代码,构建示例,并探索 JavaScript 功能。

¥Let's now move forward, looking at how we can turn these steps into code, building up the example, and exploring JavaScript features as we go.

初始设置

¥Initial setup

在开始本教程之前,我们希望你制作 number-guessing-game-start.html 文件 (在这里观看直播) 的本地副本。在文本编辑器和网络浏览器中打开它。目前,你将看到一个简单的标题、说明段落和用于输入猜测的表单,但该表单当前不会执行任何操作。

¥To begin this tutorial, we'd like you to make a local copy of the number-guessing-game-start.html file (see it live here). Open it in both your text editor and your web browser. At the moment you'll see a simple heading, paragraph of instructions and form for entering a guess, but the form won't currently do anything.

我们将添加所有代码的位置位于 HTML 底部的 <script> 元素内:

¥The place where we'll be adding all our code is inside the <script> element at the bottom of the HTML:

html
<script>
  // Your JavaScript goes here
</script>

添加变量来存储我们的数据

¥Adding variables to store our data

让我们开始吧。首先,在 <script> 元素中添加以下行:

¥Let's get started. First of all, add the following lines inside your <script> element:

js
let randomNumber = Math.floor(Math.random() * 100) + 1;

const guesses = document.querySelector(".guesses");
const lastResult = document.querySelector(".lastResult");
const lowOrHi = document.querySelector(".lowOrHi");

const guessSubmit = document.querySelector(".guessSubmit");
const guessField = document.querySelector(".guessField");

let guessCount = 1;
let resetButton;

这部分代码设置了我们需要存储程序将使用的数据的变量和常量。

¥This section of the code sets up the variables and constants we need to store the data our program will use.

变量基本上是值的名称(例如数字或文本字符串)。你可以使用关键字 let 后跟变量名称来创建变量。

¥Variables are basically names for values (such as numbers, or strings of text). You create a variable with the keyword let followed by a name for your variable.

常量也用于命名值,但与变量不同的是,一旦设置值就无法更改。在本例中,我们使用常量来存储对用户界面部分的引用。其中一些元素内的文本可能会发生变化,但每个常量始终引用与其初始化时相同的 HTML 元素。你可以使用关键字 const 后跟常量名称来创建常量。

¥Constants are also used to name values, but unlike variables, you can't change the value once set. In this case, we are using constants to store references to parts of our user interface. The text inside some of these elements might change, but each constant always references the same HTML element that it was initialized with. You create a constant with the keyword const followed by a name for the constant.

你可以使用等号 (=) 后跟要为其指定的值来为变量或常量赋值。

¥You can assign a value to your variable or constant with an equals sign (=) followed by the value you want to give it.

在我们的例子中:

¥In our example:

  • 第一个变量 — randomNumber — 被分配一个 1 到 100 之间的随机数,该数字是使用数学算法计算的。
  • 前三个常量分别用于存储对 HTML 中结果段落的引用,并用于将值插入到代码中的段落中(注意它们如何位于 <div> 元素内,该元素本身用于选择所有结果) 三个稍后,当我们重新启动游戏时进行重置):
    html
    <div class="resultParas">
      <p class="guesses"></p>
      <p class="lastResult"></p>
      <p class="lowOrHi"></p>
    </div>
    
  • 接下来的两个常量存储对表单文本输入和提交按钮的引用,并用于控制稍后提交猜测。
    html
    <label for="guessField">Enter a guess: </label>
    <input type="number" id="guessField" class="guessField" />
    <input type="submit" value="Submit guess" class="guessSubmit" />
    
  • 最后两个变量存储猜测计数 1(用于跟踪玩家的猜测次数),以及对尚不存在(但稍后会出现)的重置按钮的引用。

注意:你将从文章 存储你需要的信息 - 变量 开始,在课程稍后部分了解有关变量和常量的更多信息。

¥Note: You'll learn a lot more about variables and constants later on in the course, starting with the article Storing the information you need — Variables.

函数

¥Functions

接下来,在之前的 JavaScript 下方添加以下内容:

¥Next, add the following below your previous JavaScript:

js
function checkGuess() {
  alert("I am a placeholder");
}

函数是可重用的代码块,你可以编写一次并多次运行,从而无需一直重复代码。这真的很有用。定义函数的方法有很多种,但现在我们将集中讨论一种简单的类型。这里我们使用关键字 function 定义了一个函数,后面跟一个名称,后面加上括号。之后,我们放置两个大括号({ })。大括号内是我们每次调用该函数时想要运行的所有代码。

¥Functions are reusable blocks of code that you can write once and run again and again, saving the need to keep repeating code all the time. This is really useful. There are a number of ways to define functions, but for now we'll concentrate on one simple type. Here we have defined a function by using the keyword function, followed by a name, with parentheses put after it. After that, we put two curly braces ({ }). Inside the curly braces goes all the code that we want to run whenever we call the function.

当我们想要运行代码时,我们输入函数名称,后跟括号。

¥When we want to run the code, we type the name of the function followed by the parentheses.

现在让我们尝试一下。保存你的代码并在浏览器中刷新页面。然后进入 开发者工具 JavaScript 控制台,输入以下行:

¥Let's try that now. Save your code and refresh the page in your browser. Then go into the developer tools JavaScript console, and enter the following line:

js
checkGuess();

Return/Enter 后,你应该会看到一条警告,显示 I am a placeholder;我们在代码中定义了一个函数,每当我们调用它时都会创建一个警报。

¥After pressing Return/Enter, you should see an alert come up that says I am a placeholder; we have defined a function in our code that creates an alert whenever we call it.

注意:你稍后将在文章 函数 - 可重用的代码块 中了解有关函数的更多信息。

¥Note: You'll learn a lot more about functions later on in the article Functions — reusable blocks of code.

运算符

¥Operators

JavaScript 运算符允许我们执行测试、做数学运算、将字符串连接在一起以及其他类似的事情。

¥JavaScript operators allow us to perform tests, do math, join strings together, and other such things.

如果你还没有这样做,请保存代码,刷新浏览器中的页面,然后打开 开发者工具 JavaScript 控制台。然后我们可以尝试输入下面所示的示例 - 完全按照所示输入 "示例" 列中的每一项,在每一项后按 Return/Enter,然后查看它们返回的结果。

¥If you haven't already done so, save your code, refresh the page in your browser, and open the developer tools JavaScript console. Then we can try typing in the examples shown below — type in each one from the "Example" columns exactly as shown, pressing Return/Enter after each one, and see what results they return.

首先我们看一下算术运算符,例如:

¥First let's look at arithmetic operators, for example:

运算符 名称 示例
+ 添加 6 + 9
- 减法 20 - 15
* 乘法 3 * 7
/ 分配 10 / 5

还有一些可用的快捷操作符,称为 复合赋值运算符。例如,如果你想将一个新数字添加到现有数字并返回结果,你可以这样做:

¥There are also some shortcut operators available, called compound assignment operators. For example, if you want to add a new number to an existing one and return the result, you could do this:

js
let number1 = 1;
number1 += 2;

这相当于

¥This is equivalent to

js
let number2 = 1;
number2 = number2 + 2;

当我们运行真/假测试时(例如在条件内部 - 请参阅 below),我们使用 比较运算符。例如:

¥When we are running true/false tests (for example inside conditionals — see below) we use comparison operators. For example:

运算符 名称 示例
=== 严格平等(完全一样吗?)
js
5 === 2 + 4 // false
'Chris' === 'Bob' // false
5 === 2 + 3 // true
2 === '2' // false; number versus string
!== 不相等(是不是不一样?)
js
5 !== 2 + 4 // true
'Chris' !== 'Bob' // true
5 !== 2 + 3 // false
2 !== '2' // true; number versus string
< 少于
js
6 < 10 // true
20 < 10 // false
> 比...更棒
js
6 > 10 // false
20 > 10 // true

文本字符串

¥Text strings

字符串用于表示文本。我们已经看到了一个字符串变量:在下面的代码中,"I am a placeholder" 是一个字符串:

¥Strings are used for representing text. We've already seen a string variable: in the following code, "I am a placeholder" is a string:

js
function checkGuess() {
  alert("I am a placeholder");
}

你可以使用双引号 (") 或单引号 (') 声明字符串,但单个字符串声明的开头和结尾必须使用相同的形式:你不能写 "I am a placeholder'

¥You can declare strings using double quotes (") or single quotes ('), but you must use the same form for the start and end of a single string declaration: you can't write "I am a placeholder'.

你还可以使用反引号 (```) 声明字符串。像这样声明的字符串称为模板文字,并且具有一些特殊属性。特别是,你可以在其中嵌入其他变量甚至表达式:

¥You can also declare strings using backticks (`). Strings declared like this are called template literals and have some special properties. In particular, you can embed other variables or even expressions in them:

js
const name = "Mahalia";

const greeting = `Hello ${name}`;

这为你提供了一种将字符串连接在一起的机制。

¥This gives you a mechanism to join strings together.

条件句

¥Conditionals

回到我们的 checkGuess() 函数,我认为可以肯定地说我们不希望它只是吐出占位符消息。我们希望它检查玩家的猜测是否正确,并做出适当的反应。

¥Returning to our checkGuess() function, I think it's safe to say that we don't want it to just spit out a placeholder message. We want it to check whether a player's guess is correct or not, and respond appropriately.

此时,将当前的 checkGuess() 函数替换为此版本:

¥At this point, replace your current checkGuess() function with this version instead:

js
function checkGuess() {
  const userGuess = Number(guessField.value);
  if (guessCount === 1) {
    guesses.textContent = "Previous guesses:";
  }
  guesses.textContent = `${guesses.textContent} ${userGuess}`;

  if (userGuess === randomNumber) {
    lastResult.textContent = "Congratulations! You got it right!";
    lastResult.style.backgroundColor = "green";
    lowOrHi.textContent = "";
    setGameOver();
  } else if (guessCount === 10) {
    lastResult.textContent = "!!!GAME OVER!!!";
    lowOrHi.textContent = "";
    setGameOver();
  } else {
    lastResult.textContent = "Wrong!";
    lastResult.style.backgroundColor = "red";
    if (userGuess < randomNumber) {
      lowOrHi.textContent = "Last guess was too low!";
    } else if (userGuess > randomNumber) {
      lowOrHi.textContent = "Last guess was too high!";
    }
  }

  guessCount++;
  guessField.value = "";
  guessField.focus();
}

这是很多代码 - 唷!让我们浏览一下每个部分并解释它的作用。

¥This is a lot of code — phew! Let's go through each section and explain what it does.

  • 第一行声明一个名为 userGuess 的变量,并将其值设置为文本字段中输入的当前值。我们还通过内置的 Number() 构造函数运行这个值,只是为了确保该值绝对是一个数字。由于我们不更改此变量,因此我们将使用 const 声明它。
  • 接下来,我们遇到第一个条件代码块。条件代码块允许你根据特定条件是否为真有选择地运行代码。它看起来有点像函数,但事实并非如此。最简单形式的条件块以关键字 if 开头,然后是一些括号,然后是一些大括号。在括号内,我们包含一个测试。如果测试返回 true,我们将运行大括号内的代码。如果没有,我们就不这样做,然后继续执行下一段代码。在本例中,测试是测试 guessCount 变量是否等于 1(即这是否是玩家的第一次):
    js
    guessCount === 1;
    
    如果是,我们使猜测段落的文本内容等于 Previous guesses:。如果没有,我们就不会。
  • 接下来,我们使用模板文字将当前 userGuess 值附加到 guesses 段落的末尾,中间有一个空格。
  • 下一个块会进行一些检查:
    • 第一个 if (){ } 检查用户的猜测是否等于 JavaScript 顶部设置的 randomNumber。如果是,则玩家猜对了,游戏获胜,因此我们向玩家显示一条带有漂亮绿色的祝贺消息,清除低/高猜测信息框的内容,并运行一个名为 setGameOver() 的函数,我们将其 稍后再讨论。
    • 现在我们使用 else if (){ } 结构将另一个测试链接到最后一个测试的末尾。这个检查该回合是否是用户的最后回合。如果是,程序会执行与前一个块中相同的操作,只不过使用游戏结束消息而不是祝贺消息。
    • 链接到此代码末尾的最后一个块(else { })包含仅在其他两个测试均未返回 true 时运行的代码(即玩家没有猜对,但他们还有更多猜测)。在这种情况下,我们告诉他们他们错了,然后我们执行另一个条件测试来检查猜测是否高于或低于答案,并酌情显示进一步的消息来告诉他们更高或更低。
  • 函数中的最后三行让我们为提交下一个猜测做好准备。我们向 guessCount 变量添加 1,以便玩家用完他们的回合(++ 是增量操作 - 加 1),然后清空表单文本字段中的值并再次聚焦它,准备输入下一个猜测。

事件

¥Events

至此,我们已经有了一个很好实现的 checkGuess() 函数,但它不会执行任何操作,因为我们还没有调用它。理想情况下,我们希望在按下 "提交猜测" 按钮时调用它,为此我们需要使用事件。事件是浏览器中发生的事情 - 单击按钮、加载页面、播放视频等 - 我们可以运行代码块来响应这些事件。事件监听器观察特定事件并调用事件处理程序,事件处理程序是响应事件触发而运行的代码块。

¥At this point, we have a nicely implemented checkGuess() function, but it won't do anything because we haven't called it yet. Ideally, we want to call it when the "Submit guess" button is pressed, and to do this we need to use an event. Events are things that happen in the browser — a button being clicked, a page loading, a video playing, etc. — in response to which we can run blocks of code. Event listeners observe specific events and call event handlers, which are blocks of code that run in response to an event firing.

checkGuess() 函数下方添加以下行:

¥Add the following line below your checkGuess() function:

js
guessSubmit.addEventListener("click", checkGuess);

这里我们向 guessSubmit 按钮添加一个事件监听器。这是一个接受两个输入值(称为参数)的方法 - 我们正在监听的事件类型(在本例中为 click)作为字符串,以及我们想要在事件发生时运行的代码(在本例中为 checkGuess()) 功能)。注意,我们在 addEventListener() 中写入时不需要指定括号。

¥Here we are adding an event listener to the guessSubmit button. This is a method that takes two input values (called arguments) — the type of event we are listening out for (in this case click) as a string, and the code we want to run when the event occurs (in this case the checkGuess() function). Note that we don't need to specify the parentheses when writing it inside addEventListener().

现在尝试保存并刷新你的代码,你的示例在某种程度上应该可以工作。现在唯一的问题是,如果你猜对了正确答案或猜完了,游戏就会失败,因为我们还没有定义游戏结束后应该运行的 setGameOver() 函数。现在让我们添加缺失的代码并完成示例功能。

¥Try saving and refreshing your code now, and your example should work — to a point. The only problem now is that if you guess the correct answer or run out of guesses, the game will break because we've not yet defined the setGameOver() function that is supposed to be run once the game is over. Let's add our missing code now and complete the example functionality.

完成游戏功能

¥Finishing the game functionality

让我们将 setGameOver() 函数添加到代码底部,然后逐步执行它。现在将其添加到 JavaScript 的其余部分下方:

¥Let's add that setGameOver() function to the bottom of our code and then walk through it. Add this now, below the rest of your JavaScript:

js
function setGameOver() {
  guessField.disabled = true;
  guessSubmit.disabled = true;
  resetButton = document.createElement("button");
  resetButton.textContent = "Start new game";
  document.body.append(resetButton);
  resetButton.addEventListener("click", resetGame);
}
  • 前两行通过将表单文本输入和按钮的禁用属性设置为 true 来禁用它们。这是必要的,因为如果我们不这样做,用户可能会在游戏结束后提交更多的猜测,这会让事情变得混乱。
  • 接下来的三行生成一个新的 <button> 元素,将其文本标签设置为 "开始新游戏",并将其添加到现有 HTML 的底部。
  • 最后一行在我们的新按钮上设置一个事件监听器,以便在单击该按钮时运行一个名为 resetGame() 的函数。

现在我们也需要定义这个函数!再次将以下代码添加到 JavaScript 的底部:

¥Now we need to define this function too! Add the following code, again to the bottom of your JavaScript:

js
function resetGame() {
  guessCount = 1;

  const resetParas = document.querySelectorAll(".resultParas p");
  for (const resetPara of resetParas) {
    resetPara.textContent = "";
  }

  resetButton.parentNode.removeChild(resetButton);

  guessField.disabled = false;
  guessSubmit.disabled = false;
  guessField.value = "";
  guessField.focus();

  lastResult.style.backgroundColor = "white";

  randomNumber = Math.floor(Math.random() * 100) + 1;
}

这段相当长的代码块将所有内容完全重置为游戏开始时的状态,以便玩家可以再玩一次。它:

¥This rather long block of code completely resets everything to how it was at the start of the game, so the player can have another go. It:

  • guessCount 恢复为 1。
  • 清空信息段落中的所有文本。我们选择 <div class="resultParas"></div> 中的所有段落,然后循环遍历每个段落,将它们的 textContent 设置为 ''(空字符串)。
  • 从我们的代码中删除重置按钮。
  • 启用表单元素,清空并聚焦文本字段,准备输入新的猜测。
  • 删除 lastResult 段落的背景颜色。
  • 生成一个新的随机数,这样你就不会再次猜测相同的数字!

此时,你应该拥有一个完全可以运行(简单)的游戏 - 恭喜!

¥At this point, you should have a fully working (simple) game — congratulations!

现在我们在本文中要做的就是讨论你已经见过的其他一些重要的代码功能,尽管你可能还没有意识到。

¥All we have left to do now in this article is to talk about a few other important code features that you've already seen, although you may have not realized it.

循环

¥Loops

上述代码中我们需要更详细地了解的一部分是 for...of 循环。循环是编程中非常重要的概念,它允许你一遍又一遍地运行一段代码,直到满足特定条件。

¥One part of the above code that we need to take a more detailed look at is the for...of loop. Loops are a very important concept in programming, which allow you to keep running a piece of code over and over again, until a certain condition is met.

首先,再次转到 浏览器开发者工具 JavaScript 控制台,然后输入以下内容:

¥To start with, go to your browser developer tools JavaScript console again, and enter the following:

js
const fruits = ["apples", "bananas", "cherries"];
for (const fruit of fruits) {
  console.log(fruit);
}

发生了什么?字符串 'apples', 'bananas', 'cherries' 已在控制台中打印出来。

¥What happened? The strings 'apples', 'bananas', 'cherries' were printed out in your console.

这是因为循环。const fruits = ['apples', 'bananas', 'cherries']; 行创建一个数组。我们将在本单元稍后讨论 完整的数组指南,但现在:数组是项目(在本例中为字符串)的集合。

¥This is because of the loop. The line const fruits = ['apples', 'bananas', 'cherries']; creates an array. We will work through a complete Arrays guide later in this module, but for now: an array is a collection of items (in this case strings).

for...of 循环为你提供了一种获取数组中的每个项目并对其运行一些 JavaScript 的方法。for (const fruit of fruits) 行说:

¥A for...of loop gives you a way to get each item in the array and run some JavaScript on it. The line for (const fruit of fruits) says:

  1. 获取 fruits 中的第一项。
  2. fruit 变量设置为该项目,然后运行 {} 大括号之间的代码。
  3. 获取 fruits 中的下一项,然后重复 2,直到到达 fruits 的末尾。

在本例中,大括号内的代码将 fruit 写入控制台。

¥In this case, the code inside the curly braces is writing out fruit to the console.

现在让我们看看猜数字游戏中的循环 - 以下内容可以在 resetGame() 函数中找到:

¥Now let's look at the loop in our number guessing game — the following can be found inside the resetGame() function:

js
const resetParas = document.querySelectorAll(".resultParas p");
for (const resetPara of resetParas) {
  resetPara.textContent = "";
}

此代码使用 querySelectorAll() 方法创建一个变量,其中包含 <div class="resultParas"> 内所有段落的列表,然后循环遍历每个段落,删除每个段落的文本内容。

¥This code creates a variable containing a list of all the paragraphs inside <div class="resultParas"> using the querySelectorAll() method, then it loops through each one, removing the text content of each.

请注意,即使 resetPara 是一个常量,我们也可以像 textContent 一样更改其内部属性。

¥Note that even though resetPara is a constant, we can change its internal properties like textContent.

关于对象的小讨论

¥A small discussion on objects

在开始讨论之前,让我们再添加一项最后的改进。在 JavaScript 顶部附近的 let resetButton; 行下方添加以下行,然后保存文件:

¥Let's add one more final improvement before we get to this discussion. Add the following line just below the let resetButton; line near the top of your JavaScript, then save your file:

js
guessField.focus();

此行使用 focus() 方法在页面加载后自动将文本光标放入 <input> 文本字段,这意味着用户可以立即开始输入他们的第一个猜测,而无需先单击表单字段。这只是一个小小的补充,但它提高了可用性 - 为用户提供了一个很好的视觉线索,让他们知道他们必须做什么才能玩游戏。

¥This line uses the focus() method to automatically put the text cursor into the <input> text field as soon as the page loads, meaning that the user can start typing their first guess right away, without having to click the form field first. It's only a small addition, but it improves usability — giving the user a good visual clue as to what they've got to do to play the game.

让我们更详细地分析一下这里发生了什么。在 JavaScript 中,你将在代码中操作的大多数项目都是对象。对象是存储在单个分组中的相关功能的集合。你可以创建自己的对象,但这是相当高级的,我们要到课程稍后才会介绍它。现在,我们将简要讨论浏览器包含的内置对象,它们允许你执行许多有用的操作。

¥Let's analyze what's going on here in a bit more detail. In JavaScript, most of the items you will manipulate in your code are objects. An object is a collection of related functionality stored in a single grouping. You can create your own objects, but that is quite advanced and we won't be covering it until much later in the course. For now, we'll just briefly discuss the built-in objects that your browser contains, which allow you to do lots of useful things.

在这种特殊情况下,我们首先创建了一个 guessField 常量,用于存储对 HTML 中文本输入表单字段的引用 - 可以在代码顶部附近的声明中找到以下行:

¥In this particular case, we first created a guessField constant that stores a reference to the text input form field in our HTML — the following line can be found amongst our declarations near the top of the code:

js
const guessField = document.querySelector(".guessField");

为了获取这个引用,我们使用了 document 对象的 querySelector() 方法。querySelector() 接受一条信息 - CSS 选择器 选择你想要引用的元素。

¥To get this reference, we used the querySelector() method of the document object. querySelector() takes one piece of information — a CSS selector that selects the element you want a reference to.

因为 guessField 现在包含对 <input> 元素的引用,所以它现在可以访问许多属性(基本上是存储在对象内部的变量,其中一些变量的值不能更改)和方法(基本上是存储在对象内部的函数)。可用于输入元素的一种方法是 focus(),因此我们现在可以使用这一行来聚焦文本输入:

¥Because guessField now contains a reference to an <input> element, it now has access to a number of properties (basically variables stored inside objects, some of which can't have their values changed) and methods (basically functions stored inside objects). One method available to input elements is focus(), so we can now use this line to focus the text input:

js
guessField.focus();

不包含对表单元素的引用的变量将无法使用 focus()。例如,guesses 常量包含对 <p> 元素的引用,guessCount 变量包含数字。

¥Variables that don't contain references to form elements won't have focus() available to them. For example, the guesses constant contains a reference to a <p> element, and the guessCount variable contains a number.

玩转浏览器对象

¥Playing with browser objects

让我们玩一下一些浏览器对象。

¥Let's play with some browser objects a bit.

  1. 首先,在浏览器中打开你的程序。
  2. 接下来,打开 浏览器开发者工具,并确保 JavaScript 控制台选项卡已打开。
  3. 在控制台中输入 guessField,控制台会显示该变量包含 <input> 元素。你还会注意到控制台会自动补齐执行环境中存在的对象的名称,包括你的变量!
  4. 现在输入以下内容:
    js
    guessField.value = 2;
    
    value 属性表示输入到文本字段中的当前值。你将看到,通过输入此命令,我们已经更改了文本字段中的文本!
  5. 现在尝试在控制台中输入 guesses 并按 Enter(或 Return,具体取决于你的键盘)。控制台显示该变量包含 <p> 元素。
  6. 现在尝试输入以下行:
    js
    guesses.value;
    
    浏览器返回 undefined,因为段落没有 value 属性。
  7. 要更改段落内的文本,你需要 textContent 属性。尝试这个:
    js
    guesses.textContent = "Where is my paragraph?";
    
  8. 现在来一些有趣的东西。尝试一一输入以下行:
    js
    guesses.style.backgroundColor = "yellow";
    guesses.style.fontSize = "200%";
    guesses.style.padding = "10px";
    guesses.style.boxShadow = "3px 3px 6px black";
    
    页面上的每个元素都有一个 style 属性,该属性本身包含一个对象,该对象的属性包含应用于该元素的所有内联 CSS 样式。这允许我们使用 JavaScript 在元素上动态设置新的 CSS 样式。

暂时完成了……

¥Finished for now…

这就是构建示例的过程。你已经到了最后 - 干得好!尝试你的最终代码,或者 在这里玩我们的完成版本。如果你无法使示例正常工作,请对照 源代码 进行检查。

¥So that's it for building the example. You got to the end — well done! Try your final code out, or play with our finished version here. If you can't get the example to work, check it against the source code.