--- title: 出了什麼問題?JavaScript 疑難排解 slug: Learn/JavaScript/First_steps/What_went_wrong translation_of: Learn/JavaScript/First_steps/What_went_wrong ---
當你在練習撰寫上一節的「猜數字」遊戲時,你可能會發現它無法運作。不用擔心,本文將會把你從快被拔光的頭髮中拯救出來,並且給你一些小提示,讓你知道怎麼找出及修正Javascript的程式運行錯誤。
先備: | 基本電腦能力,基本html及css理解以及了解JavaScript是什麼 |
---|---|
目標: | 獲得開始解決簡單編碼問題的能力及信心 |
一般來說,當你的編碼有錯誤時,主要有兩種類型
好的,但事情並沒有那麼單純——當你越深入,就會發現更多不同的因素。但上述的分類已經足夠應付初期的工程師職涯了。接著,我們將更深入來討論這兩個類型。
讓我們從剛剛的猜數字遊戲開始——在這個版本中,我們將故意引入一些錯誤以便從中學習。前往Github下載一份number-game-errors.html(或運行線上版 running live here)。
Note: 你也許是想修復你自己寫的遊戲中的錯誤!這是件好事,但我們還是建議你在學習這篇文章時先使用我們的版本,這樣你才可以學到我們接下來要教的技巧。在這之後再回去修正你自己的遊戲也不遲!
現在,先讓我們來看看開發者主控台有沒有提示我們任何錯誤,然後試著修正他們。你會在接下來的段落中學到如何修正這些錯誤。
在前篇文章中我們讓你在開發者工具JavaScript console中輸入了一些JavaScript指令(如果你不記得怎麼打開這個東西,點選前面的連結複習一下)。更重要的是,主控台在瀏覽器的JavaScript引擎讀取到有語法錯誤的JavaScript時會提示一些錯誤訊息。現在讓我們來看看:
number-game-errors.html
的分頁,然後打開你的JavaScript主控台。你應該會看到如下的幾行錯誤訊息:guessSubmit.addeventListener('click', checkGuess);
addEventListener()
。addeventListener
改成addEventListener
問題就解決了。現在將你的程式碼修正吧。Note: 看看這個TypeError: "x" is not a function連結來了解更多有關這類錯誤的資訊。
Null
是一個特別的值,代表著「空」、「什麼都沒有」。lowOrHi
被宣告為一個變數,但並沒有被賦予任何有意義的值——他既沒有變數型態,也沒有值。checkGuess() { ... }
區塊中)。在之後詳細介紹函式的文章中,你會學到在函式中的程式碼與在函式外的程式碼其實是執行在不同範疇中的。在我們的這個情況裡,有錯誤的程式碼在checkGuess()
在86行被執行前都並沒有執行,也因此錯誤並沒有在頁面一載入就發生。lowOrHi.textContent = 'Last guess was too high!';
lowOrHi
的textContent
屬性設為一個字串。但是這行沒有執行成功,因為lowOrHi
並沒有存著它應該要存著的值。讓我們來看看為什麼——試試在程式碼中搜尋其他lowOrHi
有出現的地方。在第48行你會看到:
var lowOrHi = document.querySelector('lowOrHi');
null
。在第49行加上:
console.log(lowOrHi);
Note:console.log()
是一個非常好用的除錯功能,它能夠將值印出至主控台中。所以這行程式碼會在第48行賦值給lowOrHi
後,將它的值印出至主控台中。
console.log()
輸出的結果。lowOrHi
的值是null
。所以很明顯的,第 48 行一定出了什麼問題。document.querySelector()
方法來透過CSS選擇器取得一個HTML元素參照。打開我們的網頁看看我們想要取得的段落元素:
<p class="lowOrHi"></p>
querySelector()
方法的選擇器並沒有開頭的小數點。這也許就是問題所在了!試著將第48行的lowOrHi
改成.lowOrHi
。console.log()
現在應該會輸出我們想要的<p>
元素了。呼!又修好了另一個錯誤!你現在可以把你的console.log()
那行移除了,或是你想要留著之後查看——取決於你。Note: 看看這個TypeError: "x" is (not) "y" 連結來了解更多有關這類錯誤的資訊。
addeventListener
改成.addEventListener
就沒問題了。到這邊為止遊戲應該可以進行得很順利,然而玩幾次下來無疑地你會發現「隨機」數字總是0或1,這可不是我們想要的!
randomNumber
,其內容是設定遊戲一開始的隨機數字:
var randomNumber = Math.floor(Math.random()) + 1;
randomNumber = Math.floor(Math.random()) + 1;
console.log()
好朋友,將之分別放到44、113行的程式碼下一行:
console.log(randomNumber);
randomNumber
在console中總是等於1,這就是問題所在。為了修正這個錯誤,我們得先了解它是怎麼運作的。首先,我們呼叫Math.random()
以產生一個介於0到1的隨機小數,例如:0.5675493843
Math.random()
接著,我們將Math.random()
產生的隨機小數傳進Math.floor()
,函式會回傳小於等於所給數字的最大整數,然後為這個整數值加1:
Math.floor(Math.random()) + 1
由於Math.floor
是無條件捨去取整數(地板值),所以一個介於0到1的隨機小數永遠只會得到0,幫這個小數加1的話又會永遠只得到1。所以進位前我們先幫隨機小數乘上100,如此一來我們就能得到介於0到99的隨機數字了:
Math.floor(Math.random()*100);
別忘了還要加上1,數字範圍才能成功介於1到100:
Math.floor(Math.random()*100) + 1;
試著自己動手更新這兩行程式碼吧,儲存並更新頁面後你應該能看到遊戲如預期般進行!
還有些初學者非常容易忽略的小問題,這小節讓我們來概覽一下:
這個錯誤是指每行程式碼結束時必須加上英文輸入法的分號;
(請注意不要打成中文輸入法),分號被遺忘的錯誤有時不太容易發現,此外另舉一例:如果我們改動下方變數checkGuess()
中的程式碼:
var userGuess = Number(guessField.value);
改成
var userGuess === Number(guessField.value);
此時程式碼會回報錯誤,因為瀏覽器會認為你想設定不同的東西;我們需要確保自己沒有誤用、混用指派運算子(=
):用於賦予變數值跟嚴格比較運算子(===
):用於比較兩個值是否完全相等,並回覆true
/false
布林值。
Note: 更多細節請參考右方關於缺少分號的語法錯誤文章頁面: SyntaxError: missing ; before statement 。
還有另一種混用指派運算子(=
)與嚴格比較運算子(===
)的狀況,舉例如果我們將變數 checkGuess()
中的嚴格比較運算子(===
)
if (userGuess === randomNumber) {
改成指派運算子(=
)
if (userGuess = randomNumber) {
這個檢查就失效了,程式會永遠回傳 true
而勝利並結束遊戲。請小心!
給完函式或方法參數時別忘了放上)
右括號(請注意不要打成中文輸入法)。
Note: 更多細節請參考右方關於缺少右括號的語法錯誤文章頁面:SyntaxError: missing ) after argument list。
這個錯誤通常與JavaScript物件格式錯誤有關,在這個例子中,通過修改
function checkGuess() {
改成
function checkGuess( {
小心括號的部分!這會讓瀏覽器誤以為我們要把函式的程式內容當成函式參數傳入。
很簡單——這通常意味你的函式或條件結構式缺少一個大括號。若我們將checkGuess()
函式末段的一個結尾大括號刪除,就會獲得這個錯誤。
或是
這些錯誤通常意味著你漏寫一個字串起始或結尾的引號,上面第一個錯誤表示漏寫了字串開頭的起始引號,這導致這裡的「string」會替換瀏覽器發現的意外字串。第二個錯誤則表示字串結尾缺少了結束引號。
對於這些錯誤,先思考我們在範例中是如何逐項解決的。當出現錯誤資訊時,先查看該行程式碼行號,按照行號到該行程式碼察看,你可以觀察哪裡出錯了。請記住,錯誤不一定出現在該行程式碼上,而且錯誤原因也可能和我們文章上描述的問題不同!
Note:有關這些錯誤的詳細資訊,可參閱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")}}