急速 debug 實戰一(瀏覽器-基礎篇)

 

點擊上方“秋風的筆記”關注我們

前言

工欲善其事,必先利其器。最近在寫代碼的時候越發覺得不是代碼有多難,而是當代碼出了問題該如何調試,如何追溯本源,這纔是最難的。

響應這個要求,我決定寫一個關於調試實戰系列。本來不打算寫這個基礎篇章,爲了整個的完整性。(不喜勿噴)

打算出三個篇章

1.急速 debug 實戰一 (瀏覽器 - 基礎篇)

2.急速 debug 實戰二 (瀏覽器 - 線上篇)

3.急速 debug 實戰三 (Node - webpack插件,babel插件,vue源碼篇)

所以示例在以下環境通過。

操作系統: MacOS 10.13.4

Chrome: 版本 72.0.3626.81(正式版本) (64 位)

斷點調試JS

可能很多人現在還比較頻繁的用着 console.log 的方式調試着代碼,這種方式不說他絕對的不好,只是相比之下斷點有以下兩個優勢:

  • 使用 console.log(),您需要手動打開源代碼,查找相關代碼,插入 console.log()語句,然後重新加載此頁面,才能在控制檯中看到這些消息。 使用斷點,無需瞭解代碼結構即可暫停相關代碼。

  • 在 console.log() 語句中,您需要明確指定要檢查的每個值。 使用斷點,DevTools 會在暫停時及時顯示所有變量值。 有時在您不知道的情況下,有些變量會影響您的代碼。

問題

1.打開: http://yifenghua.win/example/debugger/demo1.html

2.在 Number1 文本框中輸入 5。

3.在 Number2 文本框中輸入 1。

4.點擊 AddNumber1andNumber2。 按鈕下方的標籤顯示 5+1=51。 結果應爲 6。 這就是我們需要修正的問題。

界面

第 1 步:重現錯誤

1.通過按 Command+Option+I(Mac)Control+Shift+IWindowsLinux,打開 DevTools。 此快捷方式可打開 Console 面板


2.點擊 Sources 標籤

第 3 步:使用斷點暫停代碼

如果退一步思考應用的運作方式,您可以根據經驗推測出,使用與 Add Number 1 and Number 2 按鈕關聯的 click 事件偵聽器時計算的和不正確 (5+1=51)。 因此,您可能需要在 click 偵聽器運行時暫停代碼。 Event Listener Breakpoints 可讓您完成此任務:

  1. 在 JavaScript Debugging 窗格中,點擊 Event Listener Breakpoints 以展開該部分。 DevTools 會顯示 Animation 和 Clipboard 等可展開的事件類別列表。

  2. 在 Mouse 事件類別旁,點擊 Expand Expand 圖標。 DevTools 會顯示 click 和 mousedown等鼠標事件列表。 每個事件旁都有一個複選框。

  3. 勾選 click 複選框。 DevTools 現在經過設置可以在任何 click 事件偵聽器運行時自動暫停。

  4. 返回至演示頁面,再次點擊 Add Number 1 and Number 2。 DevTools 會暫停演示並在Sources 面板中突出顯示一行代碼。 DevTools 應在此代碼行暫停:

function onClick() {

如果是在其他代碼行暫停,請按 Resume Script Execution 繼續執行腳本, 直到在正確的代碼行暫停爲止。

單步調試代碼

一個常見的錯誤原因是腳本執行順序有誤。 可以通過單步調試代碼一次一行地檢查代碼執行情況,準確找到執行順序異常之處。 立即嘗試:

在 DevTools 的 Sources 面板上,點擊 Step into next function call 單步執行時進入下一個函數調用,以便一次一行地單步調試 onClick() 函數的執行。 DevTools 突出顯示下面這行代碼:

if (inputsAreEmpty()) {

點擊 Step over next function call 單步執行時越過下一個函數調用。 DevTools 執行但不進入 inputsAreEmpty()。 請注意 DevTools 是如何跳過幾行代碼的。 這是因爲 inputsAreEmpty() 求值結果爲 false,所以 if 語句的代碼塊未執行。

這就是單步調試代碼的基本思路。 如果看一下 get-started.js 中的代碼,您會發現錯誤多半出在 updateLabel() 函數的某處。 您可以使用另一種斷點來暫停較接近極可能出錯位置的代碼,而不是單步調試每一行代碼。

設置代碼行斷點

代碼行斷點是最常見的斷點類型。 如果您想在執行到某一行代碼時暫停,請使用代碼行斷點:

看一下 updateLabel() 中的最後一行代碼:

label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;

在這行代碼的左側,您可以看到這行代碼的行號是 32。 點擊 32。 DevTools 會在 32 上方放置一個藍色圖標。 這意味着這行代碼上有一個代碼行斷點。 DevTools 現在始終會在執行此行代碼之前暫停。

點擊 Resume script execution 繼續執行腳本 。 腳本將繼續執行,直到第 32 行。 在第 29 行、第 30 行和第 31 行上,DevTools 會在各行分號右側輸出 addend1addend2sum 的值

檢查變量值

addend1addend2sum 的值疑似有問題。 這些值位於引號中,這意味着它們是字符串。 這個假設有助於說明錯誤的原因。 現在可以收集更多信息。 DevTools 可提供許多用於檢查變量值的工具。

方法 1:Scope 窗格 在某代碼行暫停時,Scope 窗格會顯示當前定義的局部和全局變量,以及各變量值。 其中還會顯示閉包變量(如果適用)。 雙擊變量值可進行編輯。 如果不在任何代碼行暫停,則 Scope 窗格爲空。

方法 2:監視表達式Watch Expressions 標籤可讓您監視變量值隨時間變化的情況。 顧名思義,監視表達式不僅限於監視變量。 您可以將任何有效的 JavaScript 表達式存儲在監視表達式中。 立即嘗試:

點擊 Watch 標籤。 點擊 Add Expression 添加表達式。 輸入 typeofsum。 按 Enter 鍵。 DevTools 會顯示 typeofsum:"string"。 冒號右側的值就是監視表達式的結果。

正如猜想,sum 的求值結果本應是數字,而實際結果卻是字符串。 現在已確定這就是錯誤的原因。

方法 3:控制檯 除了查看 console.log() 消息以外,您還可以使用控制檯對任意 JavaScript 語句求值。 對於調試,您可以使用控制檯測試錯誤的潛在解決方法。 立即嘗試:

如果您尚未打開 Console 抽屜式導航欄,請按 Escape 將其打開。 該導航欄將在 DevTools 窗口底部打開。 在 Console 中,輸入 parseInt(addend1)+parseInt(addend2)。 此語句有效,因爲您會在特定代碼行暫停,其中 addend1addend2 在範圍內。 按 Enter 鍵。 DevTools 對語句求值並打印輸出 6,即您預計演示頁面會產生的結果。

應用修正方法

您已找到修正錯誤的方法。 接下來就是嘗試通過編輯代碼並重新運行演示來使用修正方法。 您不必離開 DevTools 就能應用修正。 您可以直接在 DevTools UI 內編輯 JavaScript 代碼。 立即嘗試:

  1. 點擊 Resume script execution 繼續執行腳本。

  2. 在 Code Editor 中,將第 31 行 varsum=addend1+addend2替換爲 varsum=parseInt(addend1)+parseInt(addend2)。 3.按 Command+S(Mac) 或 Control+SWindowsLinux以保存更改。

  3. 點擊 Deactivate breakpoints 取消激活斷點。 其將變爲藍色,表示處於活動狀態。 在完成此設置後,DevTools 會忽略您已設置的任何斷點。

  4. 嘗試使用不同的值運行演示。 現在演示可以正確計算。

各類斷點使用概覽

斷點類型情況
代碼行在確切的代碼區域中。
條件代碼行在確切的代碼區域中,且僅當其他一些條件成立時。
DOM在更改或移除特定 DOM 節點或其子級的代碼中。
XHR當 XHR 網址包含字符串模式時。
事件偵聽器在觸發 click 等事件後運行的代碼中。
異常在引發已捕獲或未捕獲異常的代碼行中。
函數任何時候調用特定函數時。

代碼行斷點

在知道需要調查的確切代碼區域時,可以使用代碼行斷點。 DevTools 始終會在執行此代碼行之前暫停。

在 DevTools 中設置代碼行斷點:

  1. 點擊 Sources 標籤。

  2. 打開包含您想要中斷的代碼行的文件。

  3. 轉至代碼行。

  4. 代碼行的左側是行號列。 點擊行號列。 行號列頂部將顯示一個藍色圖標。

代碼中的代碼行斷點

在代碼中調用 debugger 可在該行暫停。 此操作相當於使用代碼行斷點,只是此斷點是在代碼中設置,而不是在 DevTools 界面中設置。

console.log('a');
console.log('b');
debugger;
console.log('c');

條件代碼行斷點

如果知道需要調查的確切代碼區域,但只想在其他一些條件成立時進行暫停,則可使用條件代碼行斷點。

若要設置條件代碼行斷點:

  1. 點擊 Sources 標籤。

  2. 打開包含您想要中斷的代碼行的文件。

  3. 轉至代碼行。

  4. 代碼行的左側是行號列。 右鍵點擊行號列。

  5. 選擇 Add conditional breakpoint。 代碼行下方將顯示一個對話框。

  6. 在對話框中輸入條件。

  7. 按 Enter 鍵激活斷點。 行號列頂部將顯示一個橙色圖標。

管理代碼行斷點

使用 Breakpoints 窗格可以從單個位置停用或移除代碼行斷點

顯示兩個代碼行斷點的 Breakpoints 窗格:一個代碼行斷點位於 get-started.js第 15 行,另一個位於

第 32 行

  • 勾選條目旁的複選框可以停用相應的斷點。

  • 右鍵點擊條目可以移除相應的斷點。

  • 右鍵點擊 Breakpoints 窗格中的任意位置可以取消激活所有斷點、停用所有斷點,或移除所有斷點。 停用所有斷點相當於取消選中每個斷點。 取消激活所有斷點可讓 DevTools 忽略所有代碼行斷點,但同時會繼續保持其啓用狀態,以使這些斷點的狀態與取消激活之前相同。

    Breakpoints 窗格中取消激活的斷點已停用且處於透明狀態

DOM 更改斷點

如果想要暫停更改 DOM 節點或其子級的代碼,可以使用 DOM 更改斷點。

若要設置 DOM 更改斷點:

  1. 點擊 Elements 標籤。

  2. 轉至要設置斷點的元素。

  3. 右鍵點擊此元素。

  4. 將鼠標指針懸停在 Break on 上,然後選擇 Subtree modificationsAttribute modifications或 Node removal

DOM 更改斷點的類型

  • Subtree modifications: 在移除或添加當前所選節點的子級,或更改子級內容時觸發這類斷點。 在子級節點屬性發生變化或對當前所選節點進行任何更改時不會觸發這類斷點。

  • Attributes modifications:在當前所選節點上添加或移除屬性,或屬性值發生變化時觸發這類斷點。

  • Node Removal:在移除當前選定的節點時會觸發。

XHR/Fetch 斷點

如果想在 XHR 的請求網址包含指定字符串時中斷,可以使用 XHR 斷點。 DevTools 會在 XHR 調用 send() 的代碼行暫停。

注:此功能還可用於 Fetch 請求。

例如,在您發現您的頁面請求的是錯誤網址,並且您想要快速找到導致錯誤請求的 AJAX 或 Fetch 源代碼時,這類斷點很有用。

若要設置 XHR 斷點:

  1. 點擊 Sources 標籤。

  2. 展開 XHR Breakpoints 窗格。

  3. 點擊 Add breakpoint

  4. 輸入要對其設置斷點的字符串。 DevTools 會在 XHR 的請求網址的任意位置顯示此字符串時暫停。

  5. 按 Enter 鍵以確認。

事件偵聽器斷點

如果想要暫停觸發事件後運行的事件偵聽器代碼,可以使用事件偵聽器斷點。 您可以選擇 click 等特定事件或所有鼠標事件等事件類別。

  1. 點擊 Sources 標籤。

  2. 展開 Event Listener Breakpoints 窗格。 DevTools 會顯示 Animation 等事件類別列表。

  3. 勾選這些類別之一以在觸發該類別的任何事件時暫停,或者展開類別並勾選特定事件。

異常斷點

如果想要在引發已捕獲或未捕獲異常的代碼行暫停,可以使用異常斷點。

  1. 點擊 Sources 標籤。

  2. 點擊 Pause on exceptions

  3.   啓用後,此按鈕變爲藍色。

  4. (可選)如果除未捕獲異常以外,還想在引發已捕獲異常時暫停,則勾選 Pause On Caught Exceptions 複選框。

函數斷點

如果想要在調用特定函數時暫停,可以調用 debug(functionName),其中 functionName 是要調試的函數。 您可以將 debug() 插入您的代碼(如 console.log() 語句),也可以從 DevTools 控制檯中進行調用。debug() 相當於在第一行函數中設置代碼行斷點。

function sum(a, b) {
  let result = a + b; // DevTools pauses on this line.
  return result;
}
debug(sum); // Pass the function object, not a string.
sum();

確保目標函數在範圍內

如果想要調試的函數不在範圍內,DevTools 會引發 ReferenceError

(function () {
  function hey() {
    console.log('hey');
  }
  function yo() {
    console.log('yo');
  }
  debug(yo); // This works.
  yo();
})();
debug(hey); // This doesn't work. hey() is out of scope.

如果是從 DevTools 控制檯中調用 debug(),則很難確保目標函數在範圍內。 下面介紹一個策略:

  1. 在函數在範圍內時設置代碼行斷點。

  2. 觸發此斷點。

  3. 當代碼仍在代碼行斷點位置暫停時,即於 DevTools 控制檯中調用 debug()

額外的調試技巧

我們在調試一些 hover 屬性的時候,往往想要調整 hover 後顯示的元素,但是每當我們移到觀察此元素的時候就會消失。這使得調試非常不方便。下面就提供幾種場景,分別來給出調試的方案。

demo: http://yifenghua.win/example/debugger/demo2.html

Hover

單純的 hover 屬性我們只需要找到觸發的元素。在這裏是我們 button。所以我們在 elements 中找到我們對應的 hover 元素。右鍵-> force state -> :hover

Mouse inner

如果是通過 mouse (鼠標事件來觸發的)並且觸發元素是寫在觸發元素內的情況。可以通過在當前觸發元素。右鍵 -> Break on -> subtree modifications。 然後再次觸發,選擇跳過斷點。就可以使得元素出現。

Mouse outer

如果是通過 mouse (鼠標事件來觸發的)並且觸發元素是寫在觸發元素外的情況。可以通過斷點觸發來阻斷。(此方法也兼容 mouser inner 的情況)。當觸發元素的時候按下 F8(Windwos) / command+\(Mac)

參考文獻

https://developers.google.com/web/tools/chrome-devtools/javascript/breakpoints?hl=zh-cn#loc

更多請關注

友情鏈接: https://huayifeng.top/

長按二維碼,可以關注我喲

萬水千山總是情,點個小贊行不行

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章