在撰寫更複雜的程式碼之前,我們來談談偵錯。
偵錯是找出並修正腳本中錯誤的過程。所有現代瀏覽器和大多數其他環境都支援偵錯工具,這是開發人員工具中的一種特殊使用者介面,可以讓偵錯變得容易許多。它也能逐行追蹤程式碼,查看實際上發生了什麼事。
我們將在此使用 Chrome,因為它有足夠的功能,大多數其他瀏覽器也有類似的流程。
「來源」面板
您的 Chrome 版本可能看起來有點不同,但仍然應該很明顯。
- 在 Chrome 中開啟範例頁面。
- 使用 F12(Mac:Cmd+Opt+I)開啟開發人員工具。
- 選取
來源
面板。
如果您是第一次這麼做,您應該會看到以下內容
切換按鈕 會開啟包含檔案的標籤頁。
讓我們按一下它,並在樹狀檢視中選取hello.js
。以下為應該會顯示的內容
來源面板有 3 個部分
- 檔案瀏覽器窗格會列出 HTML、JavaScript、CSS 和其他檔案,包括附加到網頁的圖片。Chrome 擴充功能也可能會出現在這裡。
- 程式碼編輯器窗格會顯示原始碼。
- JavaScript 除錯窗格用於除錯,我們稍後會探討。
現在您可以再次按一下相同的切換器 ,以隱藏資源清單並為程式碼騰出一些空間。
主控台
如果我們按下 Esc,主控台會在下方開啟。我們可以在這裡輸入指令並按下 Enter 來執行。
陳述式執行後,其結果會顯示在下方。
例如,這裡的 1+2
結果為 3
,而函式呼叫 hello("debugger")
沒有回傳任何值,因此結果為 undefined
中斷點
讓我們檢查一下 範例網頁 程式碼中的情況。在 hello.js
中,按一下第 4
行的號碼。是的,直接按一下 4
這個數字,而不是程式碼。
恭喜!您已設定中斷點。請也按一下第 8
行的號碼。
它應該看起來像這樣(藍色部分是您應該按一下的地方)
中斷點 是程式碼中除錯器會自動暫停 JavaScript 執行的點。
當程式碼暫停時,我們可以檢查目前的變數、在主控台中執行指令等。換句話說,我們可以除錯它。
我們可以在右邊的面板中隨時找到中斷點清單。當我們在不同的檔案中有許多中斷點時,這會很有用。它讓我們可以
- 快速跳到程式碼中的中斷點(按一下右邊的面板中的中斷點即可)。
- 暫時停用中斷點,方法是取消勾選它。
- 按一下滑鼠右鍵,然後選取 [移除],即可移除中斷點。
- …以此類推。
按一下滑鼠右鍵 於行號上,即可建立一個條件中斷點。它只會在您建立時提供的特定表達式為真時觸發。
當我們只需要針對特定變數值或特定函式參數停止時,這會很方便。
「debugger」指令
我們也可以在程式碼中使用 debugger
指令暫停程式碼,如下所示
function hello(name) {
let phrase = `Hello, ${name}!`;
debugger; // <-- the debugger stops here
say(phrase);
}
此類指令僅在開發人員工具開啟時才會運作,否則瀏覽器會忽略它。
暫停並查看周圍
在我們的範例中,hello()
會在頁面載入期間呼叫,因此在設定中斷點後,最簡單的啟動除錯器方式就是重新載入頁面。因此,讓我們按下 F5(Windows、Linux)或 Cmd+R(Mac)。
由於已設定中斷點,執行會在第 4 行暫停
請開啟右側的資訊性下拉式選單(以箭頭標示)。它們讓您可以檢查目前的程式碼狀態
-
觀察
– 顯示任何表達式的目前值。您可以按一下加號
+
並輸入表達式。除錯器會顯示其值,並在執行過程中自動重新計算其值。 -
呼叫堆疊
– 顯示巢狀呼叫鏈。目前除錯器位於
hello()
呼叫內,由index.html
中的腳本呼叫(那裡沒有函式,因此稱為「匿名」)。如果您按一下堆疊項目(例如「匿名」),除錯器會跳到對應的程式碼,且所有變數也可以檢查。
-
範圍
– 目前變數。區域
顯示區域函式變數。您也可以看到它們的值直接在來源上方以醒目方式標示。全域
有全域變數(在任何函式之外)。那裡也有
this
關鍵字,我們尚未研究,但我們很快就會研究。
追蹤執行
現在是追蹤腳本的時候了。
右側面板頂端有按鈕可以執行此動作。讓我們使用它們。
- – 「繼續執行」:繼續執行,熱鍵 F8。
-
繼續執行。如果沒有其他中斷點,則執行會繼續進行,而偵錯器會失去控制。
以下是我們點選它之後可以看到的內容
執行已繼續進行,已到達
say()
內部的另一個中斷點並在那裡暫停。查看右邊的「呼叫堆疊」。它已增加一個呼叫。我們現在位於say()
內部。 - – 「步驟」:執行下一個指令,熱鍵 F9。
-
執行下一個陳述式。如果我們現在點選它,就會顯示
alert
。一再點選它會逐一執行所有指令碼陳述式。
- – 「跨步執行」:執行下一個指令,但不要進入函式,熱鍵 F10。
-
類似於先前的「步驟」指令,但如果下一個陳述式是函式呼叫(不是內建函式,例如
alert
,而是我們自己的函式),則行為會有所不同。如果我們比較它們,「步驟」指令會進入巢狀函式呼叫,並在其第一行暫停執行,而「跨步執行」會在我們看不到的情況下執行巢狀函式呼叫,略過函式內部。
然後,執行會在該函式呼叫之後立即暫停。
如果我們對函式呼叫內部發生的事情不感興趣,這很好。
- – 「逐步執行」,熱鍵 F11。
-
這類似於「步驟」,但在非同步函式呼叫的情況下行為不同。如果你才剛開始學習 JavaScript,你可以忽略差異,因為我們還沒有非同步呼叫。
對於未來,請注意「步驟」指令會忽略稍後執行的非同步動作,例如
setTimeout
(排定的函式呼叫)。「逐步執行」會進入其程式碼,必要時等待它們。有關更多詳細資訊,請參閱 DevTools 手冊。 - – 「跳出步驟」:繼續執行直到目前函式的結尾,熱鍵 Shift+F11。
-
繼續執行並在目前函式的最後一行停止執行。當我們不小心使用 輸入巢狀呼叫,但我們對它不感興趣,而且我們想儘快繼續到它的結尾時,這很方便。
- – 啟用/停用所有中斷點。
-
該按鈕不會移動執行。僅用於中斷點的整體開/關。
- – 在發生錯誤時啟用/停用自動暫停。
-
啟用後,如果開發人員工具已開啟,腳本執行期間發生的錯誤會自動暫停執行。然後我們可以在偵錯器中分析變數,查看哪裡出錯。因此,如果我們的腳本因錯誤而中斷,我們可以開啟偵錯器,啟用此選項並重新載入頁面,以查看中斷位置及其當時的內容。
右鍵按一下程式碼行會開啟內容功能表,其中有一個稱為「繼續到此處」的絕佳選項。
當我們想要向前移動多個步驟到該行時,但又懶得設定中斷點時,這會很方便。
記錄
若要從我們的程式碼輸出一些內容到主控台,可以使用 console.log
函數。
例如,這會將值從 0
輸出到 4
到主控台
// open console to see
for (let i = 0; i < 5; i++) {
console.log("value,", i);
}
一般使用者看不到該輸出,它在主控台中。若要查看它,請開啟開發人員工具的主控台面板,或在另一個面板中按 Esc:這會在底部開啟主控台。
如果我們的程式碼中有足夠的記錄,那麼我們就可以從記錄中查看發生了什麼事,而不需要偵錯器。
摘要
正如我們所見,有三個主要方法可以暫停腳本
- 中斷點。
debugger
陳述式。- 錯誤(如果開發人員工具已開啟,且按鈕 為「開啟」)。
暫停時,我們可以進行偵錯:檢查變數並追蹤程式碼,以查看執行錯誤的地方。
開發人員工具中還有許多選項,這裡沒有涵蓋。完整的說明書位於 https://developers.google.com/web/tools/chrome-devtools。
本章節中的資訊足以開始進行偵錯,但稍後,特別是如果您進行大量的瀏覽器操作時,請前往該處並查看開發人員工具的更進階功能。
喔,您也可以按一下開發人員工具的各個位置,並查看顯示的內容。這可能是學習開發人員工具最快的途徑。別忘了右鍵按一下和內容功能表!
註解
<code>
標籤,若要插入多行程式碼,請將它們包覆在<pre>
標籤中,若要插入超過 10 行程式碼,請使用沙盒 (plnkr、jsbin、codepen…)