--- title: 查找并解决 JavaScript 代码的错误 slug: Learn/JavaScript/First_steps/What_went_wrong tags: - JavaScript - 初学者 - 开发者工具 - 指导教程 - 文章 - 调试 - 错误 translation_of: Learn/JavaScript/First_steps/What_went_wrong ---
上一节中你创建了“猜数字”游戏,但它可能没有正常工作。别担心,本节将为你提供一些简单的提示,来帮助你查找并修复JavaScript程序中的错误,从而让你远离困扰。
预备知识: | 计算机基础知识,初步理解HTML和CSS,了解JavaScript。 |
---|---|
目标: | 获得独立修复简单问题的能力和信心。 |
一般来说,代码错误主要分为两种:
事情远没有你想的那么简单,随着探究的深入,会有更多差异因素浮出水面。但在编程生涯的初级阶段上述分类方法已足矣。下面我们将依次分析。
让我们重回猜数字游戏,这次我们将故意引入一些错误。请到Github下载一份 number-game-errors.html (或 在线运行)。
注:你可能还在为修复你自己版本的游戏头疼,但我们仍然希望你先用我们的版本来完成这一节,这样你才能学到本节中的技术。然后再去修复自己的游戏也不晚。
首先查看开发者控制台,看是否存在语法错误,然后尝试修复。详见下文。
以前的课程中,你学会了在 开发工具 JavaScript 控制台 中输入一些简单的 JavaScript 命令。(如果你忘记了如何在浏览器中打开它,可以直接打开上面的链接)。更实用的是,当 JavaScript 代码进入浏览器的 JavaScript 引擎时,如果存在语法错误,控制台会提供出错信息。现在我们去看一看。
打开 number-game-errors.html
所在的标签页,然后打开 JavaScript 控制台。你将看到以下出错信息:
guessSubmit.addeventListener('click', checkGuess);
addEventListener()
。addeventListener
改为 addEventListener
便可解决。注:更多信息请参考 类型错误:“x”不是一个函数。
Null
是一个特殊值,意思是“什么也没有”,或者“没有值”。这表示 lowOrHi
已声明并初始化,但没有任何有意义的值,可以说:它没有类型没有值。checkGuess() { ... }
块中)。函数内部的代码运行于一个外部代码相互独立的域内,后面函数的文章中将更详细地讲解。此时此刻,只有当代码运行至86行并调用 checkGuess()
函数时,代码才会抛出出错信息。lowOrHi.textContent = '你猜高了!';
lowOrHi
变量中的 textContent
属性设置为一个字符串,但是失败了,这是因为 lowOrHi
并不包含预期的内容。为了一探究竟,你可以在代码中查找一下该变量的的其他实例。lowOrHi
最早出现于第 48 行:
const lowOrHi = document.querySelector('lowOrHi');
null
。在第 49 行添加以下代码:
console.log(lowOrHi);
注:console.log()
是一个非常实用的调试功能,它可以把值打印到控制台。因此我们将其置于代码第 48 行时,它会将 lowOrHi
的值打印至控制台。
console.log()
的执行结果: 显然,此处 lowOrHi
的值为 null
,所以第 48 行肯定有问题。document.querySelector()
方法和一个 CSS 选择器来取得一个元素的引用。进一步查看我们的文件,我们可以找到有问题的段落:
<p class="lowOrHi"></p>
.
),但被传递到第 48 行的querySelector()
方法中的选择器没有点。这可能是问题所在!尝试将第 48 行中的 lowOrHi
改成 .lowOrHi
。console.log()
语句应该返回我们想要的 <p>
元素。终于把错误搞定了!此时你可以把 console.log()
一行删除,或保留它以便随后参考。选择权在你。注:此错误的更多详细信息请参阅:类型错误:“x”(不)是“y”。
addeventListener
改为 addEventListener
。现在就改吧。此时,游戏应该可以顺利进行了。但经过几次试玩后你一定会注意到要猜的随机数不是 0 就是 1。这可不是我们期望的!
游戏的逻辑肯定是哪里出现了问题,因为游戏并没有返回错误,只是不能正确运行。
randomNumber
变量和首次设定随机数的代码。保存着游戏开始时玩家要猜的随机数的实例大约在 44 行:
let randomNumber = Math.floor(Math.random()) + 1;
重新开始游戏产生随机数的设定语句大约在 113 行:
randomNumber = Math.floor(Math.random()) + 1;
console.log(randomNumber);
为了解决这个问题,让我们来思考这行代码如何工作。首先,我们调用 Math.random()
,它生成一个在 0 和 1 之间的十进制随机数,例如 0.5675493843。
Math.random()
接下来,我们把调用 Math.random()
的结果作为参数传递给 Math.floor()
,它会舍弃小数部分返回与之最接近的整数。然后我们给这个结果加上1:
Math.floor(Math.random()) + 1
由于将一个 0 和 1 之间的随机小数的小数部分舍弃,返回的整数一定为 0,因此在此基础上加 1 之后返回值一定为 1。要在舍弃小数部分之前将它乘以100。便可得到 0 到 99 之间的随机数:
Math.floor(Math.random() * 100);
然后再加 1,便可得到一个 100 以内随机的自然数:
Math.floor(Math.random() * 100) + 1;
将上述两行内容替换为此,然后保存刷新,游戏终于如期运行了!
代码中还会遇到其他常见错误。 本节将指出其中的大部分。
这个错误通常意味着你漏写了一行代码最后的分号,但是此类错误有时候会更加隐蔽。例如如果我们把 checkGuess()
函数中的这一行 :
let userGuess = Number(guessField.value);
改成
let userGuess === Number(guessField.value);
将抛出一个错误。因为系统认为你在做其他事情。请不要把赋值运算符(=
,为一个变量赋值)和严格等于运算符(===
,比较两个值是否相等,返回 true
/false
)弄混淆。
注:此错误的更多详细信息请参考 SyntaxError: missing ; before statement 。
这是混淆赋值和严格等于运算符的又一症状。例如我们把 checkGuess()
里的:
if (userGuess === randomNumber) {
改成
if (userGuess = randomNumber) {
因为条件永远返回 true
,使得程序报告你猜对了。小心哦!
这个很简单。通常意味着函数/方法调用后的结束括号忘写了。
注:有关此错误的更多详细信息请参考: SyntaxError: missing ) after argument list。
JavaScript 对象的形式有错时通常会导致此类错误,如果把
function checkGuess() {
写成了
function checkGuess( {
浏览器会认为我们试图将函数的内容当作参数传回函数。写圆括号时要小心!
这个简单。通常意味着函数或条件结构中丢失了一个花括号。如果我们将 checkGuess()
函数末尾的花括号删除,就会得到这个错误。
或者
这个错误通常意味着字符串两端的引号漏写了一个。如果你漏写了字符串开始的引号,将得到第一条出错信息,这里的 'string' 将被替换为浏览器发现的意外字符。如果漏写了末尾的引号将得到第二条。
对于所有的这些错误,想想我们在实例中是如何逐步解决的。错误出现时,转到错误所在的行观察是否能发现问题所在。记住,错误不一定在那一行,错误的原因也可能和我们在上面所说的不同!
注: 有关这些错误的更多详细信息请参考:SyntaxError: Unexpected token 以及 SyntaxError: unterminated string literal。
我们有了能够在简单的 JavaScript 程序中除错的基础知识。解决代码中的错误并不总是那么简单,但至少本节内容可以为刚刚踏上学习之路的你节省出几个小时来补觉,同时让问题更快速得到解决。
{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}