概覽#
斷點(Breakpoint)是 Sources 面板的核心,能讓 JavaScript 在特定時機暫停執行,方便進行檢查。除了直接在程式碼行號上點擊建立斷點,還有非常多種更有效率的建立方式,適合不同情境。
重整頁面不會清除已建立的斷點,這也是斷點的核心機制之一。
對應到 Sources 面板右側子面板,本章會介紹下列幾種斷點:
- 標記斷點:執行到程式碼特定位置時暫停。
- 條件式斷點(Conditional Breakpoint):條件成立時才暫停。
- DOM Breakpoint:特定 DOM 元素發生變化時暫停。
- XHR Breakpoint:請求網址符合條件時暫停。
- Event Listener Breakpoint:特定事件被觸發時暫停。
- Exception 斷點:錯誤產生時暫停。
- Function 斷點:特定 Function 執行時暫停。
標記斷點#
標記斷點官方稱為 line-of-code,會在該行程式碼執行前暫停。Chrome DevTools 已支援更精細的「特定位置」標記,例如同一行用到 forEach 或 map 等迭代 Function,可以單獨對某個 callback 下斷點。
建立方式:
- 開啟 Sources 面板。
- 打開要中斷的檔案。
- 點擊行號建立斷點。
點擊行號後,右側會出現多個小箭頭,可在斷點選單中以右鍵選項跳到任一斷點位置。除了一般標記,行號的右鍵選單還能加入:
- Add conditional breakpoint:執行結果不如預期時才暫停。
- Add logpoint:相當於插入一條
console.log。 - Never pause here:可以用來跳過程式中的
debugger關鍵字。
Logpoint#
Logpoint 看起來像 console.log,但有獨特的優勢:
- 可以快速開關,不需要動到原始碼。
- 修改後重整頁面仍會保留。
- 當程式碼來自 Source Map(也就是執行的並非這份原始檔)時,編輯本身不會生效,但 Logpoint 仍可用來注入想觀察的程式碼。
debugger 關鍵字#
在程式碼裡直接寫入 debugger 也能讓 JavaScript 暫停,效果與行號斷點相同:
console.log(1);
console.log("pause");
debugger;
console.log(2);比起插一堆 console.log,搭配 debugger 的暫停可以拿到完整 Scope、調用堆疊(Call Stack)等資訊,更容易找出問題。
DOM Breakpoint#
當希望某個 DOM 元素被修改時暫停 JavaScript,可以用 DOM Breakpoint。在 Inspect 元素後從右鍵選單的 Break on 看到三種類型:
- Subtree modifications:節點底下的子節點有新增或刪除。
- Attribute modifications:節點本身的 attribute 有新增、刪除、修改。
- Node removal:該節點被移除,DOM Breakpoint 也會一併消失。
當某個元素的變化來源不明(例如莫名其妙改了顏色),用 DOM Breakpoint 可以直接定位到修改它的程式碼。
XHR Breakpoint#
Sources 面板右側選單的 XHR/Fetch Breakpoints 可以新增 URL pattern 或攔截所有請求。實務上的好處:
- 開發時各種請求齊發,能快速定位某個 API 是哪段程式碼發出。
- 暫停後續請求,避免後續日誌洗掉現場。
Event Listener Breakpoint#
展開 Event Listener Breakpoints 後可以選擇事件分類或單一事件。要特別注意的是它的暫停時機是在事件觸發後、Listener 執行前。
這是作者最推薦的一種斷點。網頁許多行為都靠事件觸發,能快速找到行為對應的程式碼,也能在調樣式時做到「JavaScript 版的狀態鎖定」。
例如想調整由 mouseenter、mouseleave 控制的 Hover 樣式,但點 DevTools 又會觸發 Blur,這種第三方套件常見的情境特別頭痛。流程:
- 勾選 Mouse >
mousedown。 - 展開選單,點擊選項觸發已註冊的
mouseenterlistener。 - 順利停在
mousedownEvent handler 第一行,選單不會關閉,可以從容調整 CSS。
Exception 斷點#
點擊右上方的八邊形暫停標誌,可以在錯誤產生時暫停。預設只攔未捕捉的錯誤,需要勾選 Pause on caught exceptions 才會包含 try-catch 中被捕捉的錯誤。
Promise 即使有 catch,reject 仍會觸發 Exception 斷點。
開啟後測試網頁能讓錯誤一發生就停在「犯罪現場」,方便檢查是否有預期外的錯誤。
Function 斷點#
Console 面板的 debug 工具相當於在某個 Function 第一行插入 debugger:
function a() {
console.log(1);
}
// 在 Console 中
debug(a);效果等同於:
function a() {
debugger;
console.log(1);
}不過 debug 建立的斷點不會出現在 Sources 面板的斷點列表,只能透過 undebug 解除。
小結#
合理組合上述斷點幾乎可以涵蓋所有 Debug 情境。除了事先設斷點外,也別忘了還有手動暫停:直接按 F8 就會立即暫停 JavaScript 執行。
下一章會接著介紹暫停之後,如何逐步執行 JavaScript 來繼續追查問題。