出了什麼問題?JavaScript 故障排除
在上一篇文章中,你構建了“猜數字”遊戲,你可能發現它無法正常工作。不用擔心——本文旨在透過提供一些關於如何在 JavaScript 程式中查詢和修復錯誤的技巧,幫助你避免因這些問題而抓狂。
| 先決條件 | 對 HTML 和 CSS 的基本瞭解,瞭解 JavaScript 是什麼。 |
|---|---|
| 目標 | 獲得開始修復自己程式碼中問題的能力和信心。 |
錯誤型別
一般來說,當你犯程式碼錯誤時,你會遇到兩種主要型別的錯誤
- 語法錯誤:這些是程式碼中的拼寫錯誤,實際上會導致程式根本無法執行,或在執行過程中停止工作——你通常也會收到一些錯誤訊息。只要你熟悉正確的工具並瞭解錯誤訊息的含義,這些錯誤通常很容易修復!
- 邏輯錯誤:這些錯誤是指語法實際上是正確的,但程式碼並非你想要的那樣,這意味著程式成功執行,但結果不正確。這些錯誤通常比語法錯誤更難修復,因為通常沒有錯誤訊息可以引導你找到錯誤的來源。
好的,所以情況並非完全那麼簡單——當你深入研究時,還有一些其他差異。但在你職業生涯的早期階段,上述分類就足夠了。我們將在後續內容中探討這兩種型別的錯誤。
一個錯誤示例
首先,讓我們回到我們的猜數字遊戲——但這次我們將探索一個引入了某些故意錯誤的版本。訪問 GitHub 併為自己建立一個本地副本 number-game-errors.html(線上檢視)。
- 首先,在您喜歡的文字編輯器和瀏覽器中開啟本地副本。
- 嘗試玩遊戲——你會注意到,當你按下“提交猜測”按鈕時,它不起作用!
注意:你可能擁有自己版本的無法正常工作的遊戲示例,你可能希望修復它!我們仍然希望你使用我們的版本完成本文,以便學習我們在這裡教授的技術。然後你可以返回並嘗試修復你的示例。
此時,讓我們查閱開發者控制檯以檢視它是否報告了任何語法錯誤,然後嘗試修復它們。你將在下面學習如何操作。
修復語法錯誤
在課程的早期,我們讓你在開發者工具 JavaScript 控制檯中輸入一些簡單的 JavaScript 命令(如果你不記得如何在瀏覽器中開啟它,請按照前面的連結瞭解如何操作)。更有用的是,只要在傳送到瀏覽器 JavaScript 引擎的 JavaScript 中存在語法錯誤,控制檯就會向你顯示錯誤訊息。現在讓我們開始搜尋吧。
- 轉到你在其中開啟
number-game-errors.html的選項卡,並開啟你的 JavaScript 控制檯。你應該會看到一條類似於以下內容的錯誤訊息:!["Number guessing game" demo page in Firefox. One error is visible in the JavaScript console: "X TypeError: guessSubmit.addeventListener is not a function [Learn More] (number-game-errors.html:86:3)".](/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong/not-a-function.png)
- 錯誤訊息的第一行是
Uncaught TypeError: guessSubmit.addeventListener is not a function number-game-errors.html:86:15
- 第一部分,
Uncaught TypeError: guessSubmit.addeventListener is not a function,告訴我們出了什麼問題。 - 第二部分,
number-game-errors.html:86:15,告訴我們程式碼中錯誤的來源:檔案“number-game-errors.html”的第 86 行,第 15 個字元。
- 第一部分,
- 如果我們在程式碼編輯器中檢視第 86 行,我們會找到以下程式碼行
警告:錯誤訊息可能不在第 86 行。
如果你使用任何帶有擴充套件程式的程式碼編輯器,該擴充套件程式會在你的本地機器上啟動一個即時伺服器,這將導致注入額外的程式碼。因此,開發者工具會將錯誤列為發生在非 86 行的位置。
jsguessSubmit.addeventListener("click", checkGuess); - 錯誤訊息顯示“guessSubmit.addeventListener is not a function”,這意味著我們呼叫的函式沒有被 JavaScript 直譯器識別。通常,此錯誤訊息實際上意味著我們拼寫錯誤。如果你不確定某個語法片段的正確拼寫,通常最好在 MDN 上查詢該功能。目前最好的方法是在你喜歡的搜尋引擎上搜索“mdn 功能名稱”。以下是一個快捷方式,可以為你節省一些時間:
addEventListener()。 - 因此,檢視此頁面,錯誤似乎在於我們拼寫錯了函式名稱!請記住,JavaScript 區分大小寫,因此任何細微的拼寫或大小寫差異都會導致錯誤。將
addeventListener更改為addEventListener應該可以解決此問題。立即執行此操作。
注意:有關此錯誤的更多詳細資訊,請參閱我們的TypeError: "x" is not a function 參考頁面。
語法錯誤第二輪
- 儲存頁面並重新整理,你應該會看到錯誤消失了。
- 現在,如果你嘗試輸入猜測並按下“提交猜測”按鈕,你將看到另一個錯誤!

- 這次報告的錯誤是
Uncaught TypeError: can't access property "textContent", lowOrHi is null
根據你使用的瀏覽器,你可能會在這裡看到不同的訊息。上面的訊息是 Firefox 會顯示的訊息,但 Chrome 例如會顯示以下訊息Uncaught TypeError: Cannot set properties of null (setting 'textContent')
這是相同的錯誤,但不同的瀏覽器以不同的方式描述它。注意:此錯誤並非在頁面載入後立即出現,因為此錯誤發生在函式內部(在
checkGuess() { }塊內)。正如你將在我們後面的函式文章中更詳細地瞭解的那樣,函式內部的程式碼與函式外部的程式碼位於不同的作用域中。在這種情況下,程式碼沒有執行,並且錯誤直到第 86 行執行checkGuess()函式時才被丟擲。 - 錯誤中給出的行號是 80。檢視第 80 行,你會看到以下程式碼js
lowOrHi.textContent = "Last guess was too high!"; - 此行試圖將
lowOrHi變數的textContent屬性設定為文字字串,但它不起作用,因為lowOrHi不包含它應該包含的內容。讓我們看看為什麼會出現這種情況——嘗試在程式碼中搜索其他lowOrHi例項。你將找到的最早的例項在第 49 行jsconst lowOrHi = document.querySelector("lowOrHi"); - 此時,我們試圖使變數包含對文件 HTML 中元素的引用。讓我們看看在執行此行程式碼後變數包含什麼。在第 50 行新增以下程式碼此程式碼將在我們嘗試在第 49 行設定js
console.log(lowOrHi);lowOrHi後將其值列印到控制檯。有關更多資訊,請參閱console.log()。 - 儲存並重新整理,你應該現在可以在控制檯中看到
console.log()結果。
的確,此時lowOrHi的值為null,這與 Firefox 錯誤訊息lowOrHi is null一致。因此第 49 行肯定存在問題。null值表示“無”或“無值”。因此,我們設定lowOrHi為元素的程式碼出錯了。 - 讓我們考慮一下可能是什麼問題。第 49 行使用
document.querySelector()方法透過使用 CSS 選擇器來獲取對元素的引用。進一步檢視我們的檔案,我們可以找到相關段落html<p class="lowOrHi"></p> - 因此,我們這裡需要一個類選擇器,它以點 (
.) 開頭,但傳遞給第 49 行中querySelector()方法的選擇器沒有點。這可能是問題所在!嘗試在第 49 行將lowOrHi更改為.lowOrHi。 - 嘗試再次儲存並重新整理,你的
console.log()語句應該會返回我們想要的<p>元素。呼!另一個錯誤已修復!你現在可以刪除你的console.log()行,或者保留它以供以後參考——由你決定。
注意:有關此錯誤的更多詳細資訊,請參閱我們的TypeError: "x" is (not) "y" 參考頁面。
語法錯誤第三輪
- 現在,如果你再次嘗試玩遊戲,你應該會取得更多成功——遊戲應該可以正常進行,直到你結束遊戲,無論是猜對了數字還是用完了猜測次數。
- 在這一點上,遊戲再次失敗,並且輸出了與我們一開始相同的錯誤——“TypeError: resetButton.addeventListener is not a function”!但是,這次它被列為來自第 94 行。
- 檢視第 94 行,很容易看出我們在這裡犯了同樣的錯誤。我們再次只需要將
addeventListener更改為addEventListener。立即執行此操作。
邏輯錯誤
此時,遊戲應該可以正常進行,但是玩過幾次後,你無疑會注意到遊戲總是選擇 1 作為你必須猜的“隨機”數字。這絕對不是我們希望遊戲進行的方式!
遊戲邏輯中肯定存在問題——遊戲沒有返回錯誤;它只是沒有正確地進行。
- 搜尋
randomNumber變數以及首次設定隨機數的行。在遊戲開始時儲存我們要猜的隨機數的例項應該在第 45 行左右jslet randomNumber = Math.floor(Math.random()) + 1; - 而在每次後續遊戲中生成隨機數的例項應該在第 113 行左右js
randomNumber = Math.floor(Math.random()) + 1; - 為了檢查這些行是否確實是問題所在,讓我們再次求助於我們的朋友
console.log()——在上述兩行程式碼的正下方插入以下程式碼行jsconsole.log(randomNumber); - 儲存並重新整理,然後玩幾局遊戲——你將看到在控制檯中記錄的每個位置
randomNumber都等於 1。
貫徹邏輯
為了解決此問題,讓我們考慮一下此行程式碼是如何工作的。首先,我們呼叫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,以生成 1 到 100 之間的隨機數。
Math.floor(Math.random() * 100) + 1;
嘗試像這樣更新這兩行程式碼,然後儲存並重新整理——遊戲現在應該按照我們的預期運行了!
其他常見錯誤
在你的程式碼中,你還會遇到其他一些常見的錯誤。本節重點介紹了其中大部分。
程式總是提示你贏了,無論你輸入什麼猜測。
這可能是混淆賦值運算子和嚴格相等運算子的另一個症狀。例如,如果我們在 checkGuess() 函式內部更改以下程式碼行:
if (userGuess === randomNumber) {
為
if (userGuess = randomNumber) {
則測試將始終返回 true,導致程式報告遊戲已獲勝。小心!
SyntaxError: missing ) after argument list
這個很簡單——它通常意味著你在函式/方法呼叫的末尾缺少了右括號。
注意:有關此錯誤的更多詳細資訊,請參閱我們的 SyntaxError: missing ) after argument list 參考頁面。
SyntaxError: missing : after property id
此錯誤通常與 JavaScript 物件格式不正確有關,但在這種情況下,我們透過更改以下程式碼獲得了此錯誤:
function checkGuess() {
為
function checkGuess( {
這導致瀏覽器認為我們試圖將函式的內容作為引數傳遞給函式。使用括號時要小心!
SyntaxError: missing } after function body
這很簡單——它通常意味著你遺漏了函式或條件結構中的某個花括號。我們透過刪除 checkGuess() 函式底部附近的某個右花括號來獲得此錯誤。
SyntaxError: expected expression, got 'string' 或 SyntaxError: string literal contains an unescaped line break
這些錯誤通常意味著你遺漏了字串值的開始或結束引號。在上面的第一個錯誤中,string 將被瀏覽器發現的意外字元替換,而不是字串開頭的引號。第二個錯誤意味著字串沒有用引號結束。
對於所有這些錯誤,請思考我們在演練中是如何解決這些示例的。當出現錯誤時,檢視給出的行號,轉到該行,看看是否能發現問題所在。請記住,錯誤不一定位於該行,而且錯誤可能不是由我們上面提到的相同問題引起的!
注意:有關這些錯誤的更多詳細資訊,請參閱我們的 SyntaxError: Unexpected token 和 SyntaxError: string literal contains an unescaped line break 參考頁面。
總結
就是這樣,關於在簡單的 JavaScript 程式中找出錯誤的基本知識。要弄清楚程式碼中的問題並不總是那麼簡單,但至少這可以為你節省幾個小時的睡眠時間,並讓你在事情不順利時更快地取得進展,尤其是在學習之旅的早期階段。
另請參閱
- 還有許多其他型別的錯誤未在此處列出;我們正在編制一份參考,詳細解釋它們的含義——請參閱 JavaScript 錯誤參考。
- 如果你在程式碼中遇到任何不確定如何修復的錯誤,請在閱讀本文後尋求幫助!在 溝通渠道 上尋求幫助。告訴我們你的錯誤是什麼,我們會盡力幫助你。列出你的程式碼也很有用。