翻译正在进行中。

现在您在学习一些关于JavaScript的理论,以及您可以拿它来做些什么。通过一个完整的练习指导,我们将会带给您一个了解JavaScript基本功能的速成课。在这里您一步接一步地将会建立一个简单的“猜数字”游戏。

前提: 基本的计算机知识,对HTML和CSS初步了解,知道JavaScript是什么。
目标: 拥有一点编写JavaScript的经验,至少会获得关于编写JavaScript时应当涉及到些什么的基本认识。

您不会被要求立即理解所有代码的细节——现在我们只是想把高级概念介绍给您,以及给您一个JavaScript(以及其他编程语言)是如何工作的。在随后的文章中,你将会再次看到这些功能的更多细节。

Note: 你在JavaScript中看到的许多代码特性和其他编程语言类似— 函数、循环,等等。 代码语法看起来不同,但是在概念上是基本类似的。

像程序员一样思考

在编程中学习的最困难的事情之一不是我们需要学习的语法,而是如何应用它来解决现实世界的问题。 您需要像一个程序员一样开始思考——这通常涉及到对程序需要做什么样描述,以及实现这些东西需要什么代码特性,以及如何使它们一起工作。

这需要努力工作,编程语法的经验和实践的混合,以及一点创造力。 我们编写的代码越多,我们的本领就越好。 我们不能保证您将在5分钟内开发“程序员大脑”,但我们将给您很多机会像整个课程中的程序员一样练习思维。

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

例子— 猜数字游戏

在本文中,我们将向您演示如何构建您在下面看到的简单游戏:

这里有个游戏,在继续阅读之前,您可以试玩几盘熟悉下规则。

不妨设想,老板给了以下要求并让您设计一个游戏

我想让你创建一个可以猜数字的游戏,它会在1~100以内随机选择一个数, 然后让玩家挑战在10轮以内猜出这个数字,每一轮都要告诉玩家正确或者错误, 如果出错了,则告诉他数字是低了还是高了,并且还要告诉玩家之前猜的数字是什么。 一旦玩家猜测正确,或者他们用完了回合,游戏将结束。 游戏结束后,可以让玩家选择再次开始。

看到这个要求,我们可以做的第一件事是开始把它分解成简单的可操作的任务,尽可能从程序员的思维去思考:

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

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

初始设置

开始本教程前,我们希望您能拷贝一份本地副本 number-guessing-game-start.html    (see it live here)。在文本编辑器和Web浏览器中打开它,此时,您将看到一个简单的标题,用于输入猜测的说明和形式段,但表单目前不会执行任何操作。

我们将添加的所有代码放在HTML底部的 <script> 元素中:

<script>

  // Your JavaScript goes here

</script>

添加变量以保存数据

让我们开始吧。 首先,在(“script”)元素中添加以下行:

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

var guesses = document.querySelector('.guesses');
var lastResult = document.querySelector('.lastResult');
var lowOrHi = document.querySelector('.lowOrHi');

var guessSubmit = document.querySelector('.guessSubmit');
var guessField = document.querySelector('.guessField');

var guessCount = 1;
var resetButton;

这部分代码设置了我们需要存储我们的程序将使用的数据的变量。 变量基本上是值的容器(例如数字或文本字符串)。 您可以使用关键字var以及变量的名称创建一个变量。 然后,您可以使用等号(=)和您要赋予的值为变量赋值。

在我们的示例中:

  • 第一个变量 - randomNumber - 被分配一个1到100之间的随机数,使用数学算法计算。
  • 接下来的三个变量都用于存储对HTML中的结果段落的引用,并用于在代码的后面段落中插入值:
  • <p class="guesses"></p>
    <p class="lastResult"></p>
    <p class="lowOrHi"></p>
  • 接下来的两个变量存储对表单文本输入和提交按钮的引用,并用于控制以后提交猜测:
    <label for="guessField">Enter a guess: </label><input type="text" id="guessField" class="guessField">
    <input type="submit" value="Submit guess" class="guessSubmit">
  • 我们的最后两个变量存储一个猜测计数1(用于跟踪玩家有多少猜测),以及一个不存在的引用(但稍后会有)。

Note: 稍后在课程中,您将学到更多关于变量的信息 , starting with the next article.

函数(Function)

接下来,在您之前写入的JavaScript代码段中添加以下内容:

function checkGuess() {
  alert('I am a placeholder');
}
函数是可重复使用的代码块,您可以“编写一次,到处运行”,从而节省了大量的重复代码。 这真的很有用。 有许多方法来定义函数,但现在我们先将注意力集中在当前这个简单的方式上。 这里我们使用关键字function定义了一个函数,后面跟着一个名字,再后面加了括号。 之后,我们放两个大括号({})。 在大括号里面,放置着当我们调用该函数时所有想要运行的代码。

该代码通过键入函数的名称后跟括号运行。

请尝试立即保存您的代码,然后在浏览器中刷新。
 

进入  developer tools JavaScript console, 并输入以下代码:

checkGuess();

您应该看到了一个警报,“I am a placeholder”; 我们在代码中定义了一个函数,当我们调用它时,函数创建了一个警报。

Note: 在课程后面你会学到更多关于函数的知识。

运算符(Operators)

JavaScript运算符允许我们执行比较,做数学运算,连接字符串,以及其他类似的事情。

让我们保存代码并刷新浏览器中显示的页面。 如果您还没有打开 developer tools JavaScript console ,或者说您无法访问浏览器开发人员工具,您可以使用使用下面所示的简单内置控制台——您可以尝试键入下面所示的示例代码,并在每个命令输入完毕之后按下Return / Enter,查看他们执行后的返回结果。 

首先让我们来看看算术运算符,例如:

Operator Name Example
+ Addition 6 + 9
- Subtraction 20 - 15
* Multiplication 3 * 7
/ Division 10 / 5

您也可以使用+运算符将文本字符串连接在一起(在编程中称为连接)。 尝试输入以下行:

var name = 'Bingo';
name;
var hello = ' says hello!';
hello;
var greeting = name + hello;
greeting;

还有一些快捷操作符可用,称为增强赋值操作符。 例如,如果您想简单地添加一个新的文本字符串到一个现有的并返回结果,您可以这样做:

name += ' says hello!';

这相当于

name = name + ' says hello!';

当我们执行true / false比较时(例如在条件语句 - 见下面),我们使用比较运算符,例如:

Operator Name Example
=== Strict equality (is it exactly the same?) 5 === 2 + 4
!== Non-equality (is it not the same?) 'Chris' !== 'Ch' + 'ris'
< Less than 10 < 6
> Greater than 10 > 20

条件(Conditionals)

回到我们的checkGuess()函数,现如今,我们不希望它只是吐出一个占位符消息。 我们希望它能够检查玩家的猜测是否正确,并做出适当的反应。

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

function checkGuess() {
  var userGuess = Number(guessField.value);
  if (guessCount === 1) {
    guesses.textContent = 'Previous guesses: ';
  }
  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!!!';
    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();
}

这有很多代码,让我们给您逐段解释它的意图。

  • 第一行(上面的第2行)声明了一个名为userGuess的变量,并将其值设置为在文本字段中输入的当前值。 我们还通过内置的Number()方法运行这个值,只是为了确保该值绝对是一个数字。
  • 接下来,我们遇到我们的第一个条件代码块(上面的第3-5行)。 条件代码块允许您根据某个条件是否为真从而选择性地运行代码。 它看起来有点像一个函数,但它不是。 条件块的最简单形式是从关键字if开始,然后是一些括号,然后是一些花括号。 在括号内,我们包含了一个比较。 如果比较返回true,就会执行放在花括号中的代码。 反之,花括号中的代码就会被跳过,从而执行下一行代码。 在这种情况下,比较是测试guessCount变量是否等于1,即玩家是不是第一次猜数字:
  • guessCount === 1
    如果是, 我们让 guesses 段落的文本内容等于"Previous guesses: "。如果不是,那就说明我们已经执行过了文本设定,那就无需再次设定了。
  • 第6行将当前userGuess值附加到guesses段落的末尾,并加上一个空格,因此在每个猜测值之间将有一个空格。
  • 下一个代码块中(上面的第8-24行)做了几个检查:
    • 第一个if(){ } 检查用户的猜测是否等于在代码顶端设置的randomNumber值。如果是,则玩家猜对了,游戏胜利,我们将向玩家显示一个漂亮的绿色的祝贺信息,并清除猜测信息框的内容,调用setgameover()方法。
    • 紧接着我们又写了一个else if(){ } 结构。它会检查这个回合是否是玩家的最后一个回合。如果是,程序将做与前一个程序块相同的事情,除了它显示的是game over而不是祝贺消息。
    • 最后的一个块是else { },其中包含着前面两个比较都为false才会执行的代码,即玩家还有游戏的次数但是本次没猜对。在这个情况下,我们会告诉玩家他们猜错了,并执行一个条件测试,判断并告诉玩家猜测的数字是大是小。
  • 这个函数最后三行 (上面的第26–28行) 让我们为下次猜测值提交做好准备。我们把guessCount变量的值+1,因此玩家消耗了一次机会 (++是一个递增操作符 — 将值+1),然后我们把文本段的值清空,重新将焦点设置在文本段里,准备下一轮游戏。

事件(Events)

现在,我们有一个实现比较不错的checkGuess()函数了,但它现在不会做任何事情,因为我们还没有调用它。 理想情况是,我们希望在按下“Submit guess”按钮时调用它,为此,我们需要使用事件。 事件是浏览器中发生的动作,例如点击按钮,加载页面或播放视频,我们可以调用代码来响应。 侦听事件发生的构造方法称为事件监听器,响应事件触发而运行的代码块被称为事件处理器

在checkGuess()函数的结束大括号后添加以下代码:

guessSubmit.addEventListener('click', checkGuess);

这里我们为guessSubmit按钮添加了一个监听事件。这个方法包含两个可输入值(参数),监听事件的类型(在本例中为“点击”),和当事件发生时我们想要执行的代码(在本例中为checkGuess()函数)——注意,当函数作为事件监听方法的参数时,函数名后不应带括号。

保存您的代码并刷新页面,示例某些功能现在应该能正常工作了。 现在唯一的问题是,如果你猜到正确的答案或游戏次数已使用完,游戏将发生错乱,因为我们还没有定义应该在游戏结束后运行的setGameOver()函数。 现在,让我们添加缺少的代码,并完成示例功能。

完善游戏

让我们将setGameOver()函数添加到代码底部,然后再来看看它:

function setGameOver() {
  guessField.disabled = true;
  guessSubmit.disabled = true;
  resetButton = document.createElement('button');
  resetButton.textContent = 'Start new game';
  document.body.appendChild(resetButton);
  resetButton.addEventListener('click', resetGame);
}
  • 前两行禁用表单文本输入和按钮,方法是将其disable属性设置为true。 这是有必要的,如果我们没有禁用,用户可以在游戏结束后提交更多的猜测,这会破坏游戏的规则。
  • 接下来的三行创建了一个新的button元素,设置它的文本为“Start new game”,并把它添加到我们文档的底部。
  • 最后一行在我们的新按钮上设置了一个事件监听器,当它被点击时,一个名为resetGame()的函数被将被调用。

现在我们需要定义resetGame()这个函数了! 将以下代码添加到代码底部:

function resetGame() {
  guessCount = 1;

  var resetParas = document.querySelectorAll('.resultParas p');
  for (var i = 0 ; i < resetParas.length ; i++) {
    resetParas[i].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;
}

这个相当长的代码块完全重置了一切:

  • 将guessCount重置为1。
  • 清除所有信息段落。
  • 从我们的代码中删除重置按钮。
  • 启用表单元素,并清空和聚焦文本字段,准备接受用户输入的新猜测。
  • 从lastResult段中删除背景颜色。
  • 生成一个新的随机数,这样下次您就是在猜测新的数字了!

现在,您应该有一个能完整工作的(简单)游戏了——恭喜您 。

我们现在来讨论下其他很重要的代码功能,你可能已经看到过,但是你可能没有意识到这一点。

循环(Loops)

上面代码的一部分,我们需要更详细地看一下 for 循环。 循环在编程中是一个非常重要的概念,它允许你一直重复运行一段代码,直到满足某个条件。

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

for (var i = 1 ; i < 21 ; i++) { console.log(i) }

发生了什么? 数字1到20在控制台中打印出来。 这是因为循环。 for循环需要三个输入值(参数):

  1. 起始值:在这种情况下,我们开始计数为1,但这可以是任何你喜欢的数字。 你可以用任何你喜欢的名字替换我,但我用作一个约定,因为它很短,很容易记住。
  2. 退出条件:这里我们指定i小于21 - 循环将继续,直到i不再小于21.当i达到21时,循环不再运行
  3. 增量:我们定义了i++,意思是向i加1。i值的每次变动都会引发循环的执行,直到i值等于21(就像上边讨论的那样)。在本例中,我们通过console.log()方法简单地在控制台打印出每次迭代时变量i的值。

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

var resetParas = document.querySelectorAll('.resultParas p');
for (var i = 0 ; i < resetParas.length ; i++) {
  resetParas[i].textContent = '';
}

此代码在<div class=“resultparas”>内使用queryselectorall()方法创建一个变量包含一个列表中的所有段落,然后依次通过每个段落,删除每个段落的文本内容。

函数的一些事

让我们再来一次最后的改进,然后再讨论。 在var resetButton下面添加以下行: 行靠近JavaScript的顶部,然后保存您的文件:

guessField.focus();

这一行使用focus() 方法立即自动地放置文本光标在输入框内,当页面加载完成时,意味着用户可以马上开始他们的第一次游戏,而不需要去点击输入框。 这只是一个小的附加,但它提高了可用性 —— 给用户提供了可视化的线索去告诉他们该怎么开始这个游戏。

让我们分析一下在这里有更多的细节。在JavaScript中,一切都是一个对象。对象是存储在单个分组中的相关功能的集合。你可以创建自己的对象,但这是相当先进的,我们现在不会谈及它,直到很晚以后的课程。现在,我们将简要讨论您的浏览器包含的内置对象,它允许您做许多有用的事情。

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

var guessField = document.querySelector('.guessField');

我们使用了document对象的querySelector()方法来获得此引用。querySelector() 需要一条信息 — — 用该元素的 CSS 选择器选择你想要的引用的元素。

因为 guessField 现在包含对 <input>的元素的引用,它现在将访问数量的属性 (存储于内部对象的其中一些不会更改其值的基础变量) 和方法 (存储在对象内部的基础函数)。一种方法可用来输入元素是 focus (),所以我们现在可以使用这条线集中文本输入︰

guessField.focus();

不包含对表单元素引用的变量不会有 focus () 方法可供它们执行。例如,guesses变量包含对 <p>元素的引用和 guessCount 包含了一个数字。

Playing with browser objects

Let's play with some browser objects a bit.

  1. First of all open your program up in a browser.
  2. Next, open your browser developer tools, and make sure the JavaScript console tab is open.
  3. Type in guessField and the console will show you that the variable contains an <input> element. You'll also notice that the console autocompletes object names that exist inside the execution environment, including your variables!
  4. Now type in the following:
    guessField.value = 'Hello';
    The value property represents the current value entered into the text field. You'll see that by entering this command, we've changed what that is!
  5. Now try typing in guesses and pressing return. The console will show you that the variable contains a <p> element.
  6. Now try entering the following line:
    guesses.value
    The browser will return undefined, because value doesn't exist on paragraphs.
  7. To change the text inside a paragraph, you need the textContent property instead. Try this:
    guesses.textContent = 'Where is my paragraph?';
  8. Now for some fun stuff. Try entering the below lines, one by one:
    guesses.style.backgroundColor = 'yellow';
    guesses.style.fontSize = '200%';
    guesses.style.padding = '10px';
    guesses.style.boxShadow = '3px 3px 6px black';
  9. 页面上的每个元素都有一个style属性,它本身包含一个对象,其属性包含应用于该元素的所有内联CSS样式。 这允许我们使用JavaScript在元素上动态设置新的CSS样式。

 

完成了...

所以这是为了建立这个例子你得到了结束,做得好! 尝试你的最终代码,或者看看我们的版本.如果你不能让示例工作,请检查它 source code.

文档标签和贡献者

 最后编辑者: iyang,