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

前言

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

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

注意,如下yifenghua.win域名下線,替換爲https://hua1995116.github.io/myblog/vue

打算出三個篇章java

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

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

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

因此示例在如下環境經過。web

操做系統: MacOS 10.13.4chrome

Chrome: 版本 72.0.3626.81(正式版本) (64 位)瀏覽器

斷點調試JS

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

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

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

問題

1.打開: hua1995116.github.io/myblog/exam…

2.在 Number 1 文本框中輸入 5。

3.在 Number 2 文本框中輸入 1。

4.點擊 Add Number 1 and Number 2。 按鈕下方的標籤顯示5 + 1 = 51。 結果應爲 6。 這就是咱們須要修正的問題。

2019-02-14-01.png

界面

第 1 步:重現錯誤

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

2019-02-14-02.png

2.點擊 Sources 標籤。

2019-02-14-03.png

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

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

  1. JavaScript Debugging 窗格中,點擊 Event Listener Breakpoints 以展開該部分。 DevTools 會顯示 AnimationClipboard 等可展開的事件類別列表。
  2. Mouse 事件類別旁,點擊 Expand Expand 圖標。 DevTools 會顯示 clickmousedown 等鼠標事件列表。 每一個事件旁都有一個複選框。
  3. 勾選 click 複選框。 DevTools 如今通過設置能夠在任何 click 事件偵聽器運行時自動暫停。
  4. 返回至演示頁面,再次點擊 Add Number 1 and Number 2。 DevTools 會暫停演示並在 Sources 面板中突出顯示一行代碼。 DevTools 應在此代碼行暫停:
function onClick() {
複製代碼

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

2019-02-14-04.png

單步調試代碼

一個常見的錯誤緣由是腳本執行順序有誤。 能夠經過單步調試代碼一次一行地檢查代碼執行狀況,準確找到執行順序異常之處。 當即嘗試:

在 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 的值。

2019-02-14-05.png

檢查變量值

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

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

2019-02-14-06.png

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

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

2019-02-14-07.png

正如猜測,sum 的求值結果本應是數字,而實際結果倒是字符串。 如今已肯定這就是錯誤的緣由。

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

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

2019-02-14-08.png

應用修正方法

您已找到修正錯誤的方法。 接下來就是嘗試經過編輯代碼並從新運行演示來使用修正方法。 您沒必要離開 DevTools 就能應用修正。 您能夠直接在 DevTools UI 內編輯 JavaScript 代碼。 當即嘗試:

  1. 點擊 Resume script execution 繼續執行腳本。
  2. Code Editor 中,將第 31 行 var sum = addend1 + addend2替換爲 var sum = parseInt(addend1) + parseInt(addend2)。 3.按 Command+S (Mac)Control+S(Windows、Linux)以保存更改。
  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 modificationsNode 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. (可選)若是除未捕獲異常之外,還想在引起已捕獲異常時暫停,則勾選 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: hua1995116.github.io/myblog/exam…

2019-02-16-01.png

Hover

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

Kapture2019-02-16-01.gif

Mouse inner

若是是經過 mouse (鼠標事件來觸發的)而且觸發元素是寫在觸發元素內的狀況。能夠經過在當前觸發元素。右鍵 -> Break on -> subtree modifications。 而後再次觸發,選擇跳過斷點。就可使得元素出現。

Kapture2019-02-16-02.gif

Mouse outer

若是是經過 mouse (鼠標事件來觸發的)而且觸發元素是寫在觸發元素外的狀況。能夠經過斷點觸發來阻斷。(此方法也兼容 mouser inner 的狀況)。當觸發元素的時候按下 F8 (Windwos) / command + \ (Mac)

Kapture2019-02-16-03.gif

參考文獻

developers.google.com/web/tools/c…

更多請關注

友情連接: huayifeng.top/

相關文章
相關標籤/搜索