--- title: JavaScript 初体验 slug: Learn/JavaScript/First_steps/A_first_splash tags: - JavaScript - 事件 - 函数 - 初学者 - 变量 - 学习 - 操作符 - 教程 - 添加 translation_of: Learn/JavaScript/First_steps/A_first_splash ---
现在,你已经学到了一些 JavaScript 的理论知识,以及用 JavaScript 能够做些什么。下面我们会提供一个讲解 Javascript 基本特性的 Crash Course,课程是一个全面的实践性项目——循序渐进地构建一个简易版“猜数字”游戏。
预备知识: | 计算机基础知识,初步理解HTML和CSS,了解JavaScript。 |
---|---|
目标: | 获得编写JavaScript的初体验,初步了解编写JavaScript时会涉及哪些内容。 |
我们并不要求你立刻完整理解所有代码,当前只是概括地介绍一些抽象的概念,并且让你对JavaScript(以及其他编程语言)工作原理有一定的认知。所有具体特性将在后续文章中详细介绍。
注: 可以看到,JavaScript 中许多代码特性和其他编程语言是一致的( 函数、循环,等等)。尽管代码语法不尽相同,但概念基本类似。
学习编程,语法本身并不难,真正困难的是如何应用它来解决现实世界的问题。 你要开始像程序员那样思考。一般来讲,这种思考包括了解你程序运行的目的,为达到该目的应选定的代码类型,以及如何使这些代码协同运行。
为达成这一点,我们需要努力编程,获取语法经验,注重实践,再加一点创造力,几项缺一不可。代码写的越多,就会完成的越优秀。虽然我们不能保证你在5分钟内拥有“程序员大脑”,但是整个课程中你将得到大量机会来训练程序员思维。
请牢记这一点,然后开始观察本文的示例,体会一下将其分解为可操作任务的大体过程。
本文将向你演示如何构建下面的小游戏:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>猜数字游戏</title> <style> html { font-family: sans-serif; } body { width: 50%; max-width: 800px; min-width: 480px; margin: 0 auto; } .lastResult { color: white; padding: 3px; } </style> </head> <body> <h1>猜数字游戏</h1> <p>我刚才随机选定了一个100以内的自然数。看你能否在 10 次以内猜中它。每次我都会告诉你所猜的结果是高了还是低了。</p> <div class="form"> <label for="guessField">请猜数: </label><input type="text" id="guessField" class="guessField"> <input type="submit" value="确定" class="guessSubmit"> </div> <div class="resultParas"> <p class="guesses"></p> <p class="lastResult"></p> <p class="lowOrHi"></p> </div> </body> <script> // 在此放置你的 JavaScript 代码 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; function checkGuess() { let userGuess = Number(guessField.value); if (guessCount === 1) { guesses.textContent = '上次猜的数: '; } guesses.textContent += userGuess + ' '; if (userGuess === randomNumber) { lastResult.textContent = '恭喜你!猜对了!'; lastResult.style.backgroundColor = 'green'; lowOrHi.textContent = ''; setGameOver(); } else if (guessCount === 10) { lastResult.textContent = '!!!GAME OVER!!!'; lowOrHi.textContent = ''; setGameOver(); } else { lastResult.textContent = '你猜错了!'; lastResult.style.backgroundColor = 'red'; if(userGuess < randomNumber) { lowOrHi.textContent='刚才你猜低了!' ; } else if(userGuess > randomNumber) { lowOrHi.textContent = '刚才你猜高了!'; } } guessCount++; guessField.value = ''; } guessSubmit.addEventListener('click', checkGuess); function setGameOver() { guessField.disabled = true; guessSubmit.disabled = true; resetButton = document.createElement('button'); resetButton.textContent = '开始新游戏'; document.body.appendChild(resetButton); resetButton.addEventListener('click', resetGame); } function resetGame() { guessCount = 1; const 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; } </script> </html>
{{ EmbedLiveSample('Top_hidden_code', '100%', 320, "", "", "hide-codepen-jsfiddle") }}
先玩上几盘,在继续之前先熟悉一下这个游戏。
假设你的老板给你布置了以下游戏设计任务要求:
我想让你开发一个猜数字游戏。游戏应随机选择一个 100 以内的自然数, 然后邀请玩家在 10 轮以内猜出这个数字。每轮后都应告知玩家的答案正确与否,如果出错了,则告诉他数字是低了还是高了。并且应显示出玩家前一轮所猜的数字。一旦玩家猜对,或者用尽所有机会,游戏将结束。游戏结束后,可以让玩家选择再次开始。
看到这个要求,首先我们要做的是将其分解成简单的可操作的任务,尽可能从程序员的思维去思考:
让我们继续,看看我们如何将这些步骤转换为代码,构建这个示例,从而探索 JavaScript 的功能。
本教程开始前,请将 number-guessing-game-start.html 文件保存下来。同时在文本编辑器和Web浏览器中将其打开,可以看到一个简单的标题,一段游戏说明,和一个用于输入猜测的表单,此时表单不会执行任何操作。
我们将在 HTML 底部的 {{htmlelement("script")}} 元素中添加新的代码:
<script>
// 开始编写 JavaScript 代码
</script>
让我们开始吧。首先,在 {{htmlelement("script")}} 元素中添加以下代码:
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;
这段代码设置了存储数据的变量和常量以供程序使用。变量本质上是值(例如数字或字符串)的容器。 你可以使用关键字 let
(旧代码中使用 var
)和一个名字来创建变量(请参阅 let 和 var 之间的区别)。常量用于存储不希望更改的数据,用关键字 const
创建,本例中用常量来保存对界面元素的引用。界面元素的文字可能会改变,但引用是不变的。
可以使用等号(=)和一个值来为变量赋值。
在我们的示例中:
randomNumber
)。<p class="guesses"></p> <p class="lastResult"></p> <p class="lowOrHi"></p>
<label for="guessField">请猜数:</label> <input type="text" id="guessField" class="guessField"> <input type="submit" value="确定" class="guessSubmit">
注: 稍后将讲解更多关于变量/常量的信息。参见下节。
下面,在之前的代码中添加以下内容:
function checkGuess() { alert('我是一个占位符'); }
checkGuess();
在按下 Return/Enter 之后,你应该会看到一个告警窗口,显示 "我是一个占位符
";我们在代码中定义了一个函数,当我们调用它时,函数创建了一个告警窗口。
注: 后续课程 将讲解更多有关函数的知识。
JavaScript 运算符允许我们执行比较,做数学运算,连接字符串,以及其他类似的事情。
请保存代码以免丢失,然后刷新浏览器页面,打开 开发者工具 JavaScript 控制台。然后我们就可以尝试下文中的示例了:把下表中“示例”一列中的每一项都原封不动输入进来,每次输入完毕后都按下 Return/Enter ,可以看到返回的结果。如果你无法访问浏览器开发者工具,你随时都可以使用下面的简易版内置控制台。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>JavaScript console</title> <style> * { box-sizing: border-box; } html { background-color: #0C323D; color: #809089; font-family: monospace; } body { max-width: 700px; } p { margin: 0; width: 1%; padding: 0 1%; font-size: 16px; line-height: 1.5; float: left; } .input p { margin-right: 1%; } .output p { width: 100%; } .input input { width: 96%; float: left; border: none; font-size: 16px; line-height: 1.5; font-family: monospace; padding: 0; background: #0C323D; color: #809089; } div { clear: both; } </style> </head> <body> </body> <script> var geval = eval; function createInput() { var inputDiv = document.createElement('div'); var inputPara = document.createElement('p'); var inputForm = document.createElement('input'); inputDiv.setAttribute('class','input'); inputPara.textContent = '>'; inputDiv.appendChild(inputPara); inputDiv.appendChild(inputForm); document.body.appendChild(inputDiv); inputDiv.focus(); inputForm.addEventListener('change', executeCode); } function executeCode(e) { try { var result = geval(e.target.value); } catch(e) { var result = 'error — ' + e.message; } var outputDiv = document.createElement('div'); var outputPara = document.createElement('p'); outputDiv.setAttribute('class','output'); outputPara.textContent = 'Result: ' + result; outputDiv.appendChild(outputPara); document.body.appendChild(outputDiv); e.target.disabled = true; e.target.parentNode.style.opacity = '0.5'; createInput() } createInput(); </script> </html>
{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}
首先让我们来看看算术运算符,例如:
运算符 | 名称 | 示例 |
---|---|---|
+ |
加 | 6 + 9 |
- |
减 | 20 - 15 |
* |
乘 | 3 * 7 |
/ |
除 | 10 / 5 |
您也可以使用 +
运算符将文本字符串连接在一起(术语“串联”(concatenation))。 尝试依次输入以下行:
let name = 'Bingo'; name; let hello = ' says hello!'; hello; let greeting = name + hello; greeting;
还有一些快捷操作符可用,称为 复合赋值操作符。 例如,如果你只希望在现有字符串末尾添加一个新串,可以这样做:
name += ' says hello!';
这等价于:
name = name + ' says hello!';
在执行真/假比较时(例如在条件语句中,见 {{anch("Conditionals", "下表")}}),我们使用 比较运算符,例如:
运算符 | 名称 | 示例 |
---|---|---|
=== |
严格等于(它们是否完全一样?) | 5 === 2 + 4 |
!== |
不等于(它们究竟哪里不一样?) | 'Chris' !== 'Ch' + 'ris' |
< |
小于 | 10 < 6 |
> |
大于 | 10 > 20 |
回到我们的 checkGuess()
函数,我们希望它不仅能够给出一个占位符消息,同时还能检查玩家是否猜对,并做出适当的反应。我想这并不难吧。
现在,将当前的 checkGuess()
函数替换为此版本:
function checkGuess() { let userGuess = Number(guessField.value); if (guessCount === 1) { guesses.textContent = '上次猜的数:'; } guesses.textContent += userGuess + ' '; if (userGuess === randomNumber) { lastResult.textContent = '恭喜你!猜对了'; lastResult.style.backgroundColor = 'green'; lowOrHi.textContent = ''; setGameOver(); } else if (guessCount === 10) { lastResult.textContent = '!!!GAME OVER!!!'; setGameOver(); } else { lastResult.textContent = '你猜错了!'; lastResult.style.backgroundColor = 'red'; if(userGuess < randomNumber) { lowOrHi.textContent = '你猜低了!'; } else if(userGuess > randomNumber) { lowOrHi.textContent = '你猜高了'; } } guessCount++; guessField.value = ''; guessField.focus(); }
唷——好多的代码!让我们来逐段探究。
userGuess
的变量,并将其设置为在文本字段中输入的值。 我们还对这个值应用了内置的 Number()
方法,只是为了确保该值是一个数字。if
开始,然后是一些括号,然后是一些花括号。 括号内包含一个比较。 如果比较结果为 true
,就会执行花括号内的代码。 反之,花括号中的代码就会被跳过,从而执行下面的代码。 本文的示例中,比较测试的是 guessCount
变量是否等于1,即玩家是不是第一次猜数字:guessCount === 1
如果是, 我们让 guesses
段落的文本内容等于“上次猜的数:
”。如果不是就不用了。
userGuess
值附加到 guesses
段落的末尾,并加上一个空格,以使每两个猜测值之间有一个空格。if(){ }
检查用户的猜测是否等于在代码顶端设置的 randomNumber
值。如果是,则玩家猜对了,游戏胜利,我们将向玩家显示一个漂亮的绿色的祝贺信息,并清除“高了 / 低了”信息框的内容,调用 setGameOver()
方法。else if(){ }
结构。它会检查这个回合是否是玩家的最后一个回合。如果是,程序将做与前一个程序块相同的事情,只是这次它显示的是 Game Over 而不是祝贺消息。else { }
,前两个比较都不返回 true
时(也就是玩家尚未猜对,但是还有机会)才会执行这里的代码。在这个情况下,我们会告诉玩家他们猜错了,并执行另一个条件测试,判断并告诉玩家猜测的数字是高了还是低了。guessCount
变量的值加 1,以使玩家消耗一次机会 (++
是自增操作符,为自身加 1),然后我们把表单中文本域的值清空,重新聚焦于此,准备下一轮游戏。现在,我们有一个实现比较不错的 checkGuess()
函数了,但它现在什么事情也做不了,因为我们还没有调用它。 理想中,我们希望在点击“确定”按钮时调用它,为此,我们需要使用事件。 事件就是浏览器中发生的事儿,比如点击按钮、加载页面、播放视频,等等,我们可以通过调用代码来响应事件。 侦听事件发生的结构称为事件监听器(Event Listener),响应事件触发而运行的代码块被称为事件处理器(Event Handler)。
在 checkGuess()
函数后添加以下代码:
guessSubmit.addEventListener('click', checkGuess);
这里为 guessSubmit
按钮添加了一个事件监听器。addEventListener()
方法包含两个可输入值(称为“参数”(argument)),监听事件的类型(本例中为“click
”),和当事件发生时我们想要执行的代码(本例中为 checkGuess()
函数)。注意,addEventListener()
中作为参数的函数名不加括号。
现在,保存代码并刷新页面,示例应该能够工作了,但还不够完善。 现在唯一的问题是,如果玩家猜对或游戏次数用完,游戏将出错,因为我们尚未定义游戏结束时应运行的setGameOver()
函数。 现在,让我们补全所缺代码,并完善示例功能。
在代码最后添加一个 setGameOver()
函数,然后我们一起来看看它:
function setGameOver() { guessField.disabled = true; guessSubmit.disabled = true; resetButton = document.createElement('button'); resetButton.textContent = '开始新游戏'; document.body.appendChild(resetButton); resetButton.addEventListener('click', resetGame); }
disable
属性设置为 true
来禁用表单文本输入和按钮。 这样做是必须的,否则用户就可以在游戏结束后提交更多的猜测,游戏的规则将遭到破坏。resetGame()
的函数被将被调用。现在我们需要定义 resetGame()
这个函数,依然放到代码底部:
function resetGame() { guessCount = 1; const resetParas = document.querySelectorAll('.resultParas p'); for (let 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
段落的背景颜色。此刻一个能功能完善的(简易版)游戏就完成了。恭喜!
我们现在来讨论下其他很重要的代码功能,你可能已经看到过,但是你可能没有意识到这一点。
上面代码中有一部分需要我们仔细研读,那就是 for 循环。 循环是一个非常重要的编程概念,它让你能够重复运行一段代码,直到满足某个条件为止。
首先,请再次转到 浏览器开发工具 JavaScript 控制台 然后输入以下内容:
for (let i = 1; i < 21; i++) { console.log(i); }
发生了什么? 控制台中打印出了数字 1 到 20。 这正是循环所为。一个 for 循环需要三个输入值(参数):
i
也可以用任何你喜欢的名字替换,但一般约定用 i
,因为它很短,且易于记忆。i < 21
,直到i
不再小于 21 前循环将继续。当 i
达到 21 时,循环将退出。i++
,意思是向 i
加 1。i
值的每次变动都会引发循环的执行,直到 i
值等于 21(如前文所讲)。为简化问题,在本例中,我们使用console.log()
在控制台打印出每次迭代时变量 i
的值。现在让我们来观察猜数字游戏中的循环 —— resetGame()
函数中可以找到以下内容:
let resetParas = document.querySelectorAll('.resultParas p'); for (let i = 0 ; i < resetParas.length ; i++) { resetParas[i].textContent = ''; }
这段代码通过 {{domxref("Document.querySelectorAll", "querySelectorAll()")}} 方法创建了一个包含 <div class="resultParas">
内所有段落的变量,然后通过循环迭代,删除每个段落的文本内容。
在讨论前最后再改进一波。 在 let resetButton
(脚本顶端部分)下方添加下面一行内容,然后保存文件:
guessField.focus();
这一行通过 {{domxref("HTMLElement.focus", "focus()")}} 方法让光标在页面加载完毕时自动放置于 {{htmlelement("input")}} 输入框内,这意味着玩家可以马上开始第一次猜测,而无需点击输入框。 这只是一个小的改进,却提高了可用性——为使用户能投入游戏提供一个良好的视觉线索。
深入分析一下。JavaScript 中一切都是对象。对象是存储在单个分组中的相关功能的集合。可以创建自己的对象,但这是较高阶的知识,我们今后才会谈及。现在,仅需简要讨论浏览器内置的对象,它们已经能够做许多有用的事情。
在本示例的特定情况下,我们首先创建一个 guessField
常量来存储对 HTML 中的文本输入表单域的引用,在文档顶部的声明区域中可以找到以下行:
const guessField = document.querySelector('.guessField');
使用 {{domxref("document")}} 对象的 {{domxref("document.querySelector", "querySelector()")}} 方法可以获得这个引用。querySelector()
需要一个信息——用一个 CSS选择器 可以选中需要引用的元素。
因为 guessField
现在包含一个指向 {{htmlelement("input")}} 元素的引用,它现在就能够访问一系列的属性(存储于对象内部的基础变量,其中一些的值无法改变)和方法(存储在对象内部的基础函数)。focus()
是 {{htmlelement("input")}} 元素可用方法之一,因此我们可以使用这行代码将光标聚焦于此文本框上︰
guessField.focus();
不包含对表单元素引用的变量不提供 focus()
方法。例如,引用 {{htmlelement("p")}} 元素的guesses
常量,包含一个数字的 guessCount
变量。
浏览器对象如何使用呢,下面我们来小试牛刀。
guessField
,控制台将会显示此变量包含一个 {{htmlelement("input")}} 元素。同时控制台还能自动补全运行环境中对象的名字,包括你的变量!guessField.value = 'Hello';
value
属性表示当前文本区域中输入的值。 在输入这条指令后,你将看到文本域区中的文本被我们修改了!guesses
然后回车。控制台会显示一个包含 {{htmlelement("p")}} 元素的变量。guesses.value浏览器会返回
undefined
,因为段落中并不存在 value
。value
。试试这个:
guesses.textContent = '我的段落在哪里?';
guesses.style.backgroundColor = 'yellow'; guesses.style.fontSize = '200%'; guesses.style.padding = '10px'; guesses.style.boxShadow = '3px 3px 6px black';
style
属性,它本身包含一个对象,其属性包含应用于该元素的所有内联 CSS 样式。 让我们可以使用 JavaScript 在元素上动态设置新的 CSS 样式。这个示例已经构建完毕,做得好!来尝试运行一下最终的代码,或者 看看我们的最终版本。如果你的版本无法正常工作,请对照 源代码 进行检查。
{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}