原鏈接:https://www.zhihu.com/question/35667558/answer/530643532
編程新手剛開始查找和修復 bug 還是比較困難的饱亮,你可能會隨機使用 console.log()矾芙,試圖讓代碼正確運行〗希看了本文再也不用這么干了剔宪!
下面就教你一個調(diào) bug 的正確姿勢。你會學習如何使用 Chrome 開發(fā)者工具設(shè)置斷點壹无,逐步調(diào)試代碼葱绒。這種工作方法能讓你查找和修復 bug 的效率大幅提高。
雖然這篇教程展示的是怎么調(diào)試一個具體的 bug斗锭,但是整體工作思路對調(diào)試任何類型的 JavaScript bug 都是有指導意義的地淀。
步驟1:重現(xiàn) bug
調(diào)試 bug 的第一步就是重現(xiàn) bug。所謂“重現(xiàn) bug”就意味著要找到一系列持續(xù)導致出現(xiàn)這個 bug 的操作岖是。你可能需要多次重現(xiàn) bug帮毁,所以盡可能地減少不必要的步驟。
按照如下指令來重現(xiàn)本教程需要修復的 bug璧微。
這是我們本教程會使用的網(wǎng)頁作箍,確保以新的標簽:Demo: Get Started Debugging JavaScript with Chrome DevTools
在 demo 中,在“Number 1”文本框中輸入 5
在“Number 2”文本框中輸入數(shù)字 2
點擊“Add Number 1 and Number 2”按鈕
查看輸入和按鈕下方的標簽前硫,顯示 5 + 1 = 51.
這不胞得,bug 來了,這里結(jié)果明顯錯了屹电,應(yīng)該是 6阶剑。這就是你要修復的 bug。
步驟2:使用斷點暫停代碼
Chrome 開發(fā)者工具(以下簡稱 DevTools)能讓你在代碼運行期間暫停代碼危号,并檢查此刻所有變量的值牧愁。暫停代碼的工具叫做 Breakpoint。試試吧:
回到 demo外莲,按 Command+Option(Mac)或 Ctrl+shift+I(Windows猪半,Linux)打開DevTools
點擊“Source”標簽
點擊“Event Listener Breakpoints”(事件監(jiān)聽斷點)展開該部分。DevTools 會展示一列可擴展的事件類別偷线,比如 Animation和Clipboard
在“Mouse”事件類別旁邊點擊“Expand”
檢查“click”復選框
<img src="https://pic2.zhimg.com/v2-59cc59b530364c601a704dc3b5a5a509_b.jpg" data-caption="" data-size="normal" data-rawwidth="800" data-rawheight="536" class="origin_image zh-lightbox-thumb" width="800" data-original="https://pic2.zhimg.com/v2-59cc59b530364c601a704dc3b5a5a509_r.jpg">
回到 demo磨确,再次點擊“Add Number 1 and Number 2”.DevTools 會暫停 demo,在“Source”面板上高亮顯示一行代碼声邦,高亮顯示的是:
function onClick() {
為啥乏奥?
當你選擇“Click”時,會在所有的 click 事件上設(shè)置一個基于事件的斷點亥曹。每當節(jié)點被點擊邓了,并且節(jié)點有 click 處理程序時恨诱,DevTools 就會在該節(jié)點的 click 處理程序的第一行代碼處自動暫停。
這里還是要推薦下小編的web前端學習群:867726593骗炉,不管你是小白還是大牛照宝,小編我都歡迎,不定期分享干貨痕鳍,包括小編自己整理的一份最新的web前端資料和0基礎(chǔ)入門教程硫豆,歡迎初學和進階中的小伙伴龙巨。在不忙的時間我會給大家解惑笼呆。
步驟3:逐步調(diào)試代碼
導致出現(xiàn) bug 的一個常見原因就是腳本運行順序不正確。逐步調(diào)試代碼能讓你過一遍你的代碼運行狀況旨别,每次一行诗赌,準確找出哪里沒有按照預期的順序執(zhí)行。試試:
在 DevTools 的“Source”面板上秸弛,點擊“Step into next function call”
<img src="https://pic3.zhimg.com/v2-3e17e85ee8b8e70d904c1c4d776b292a_b.jpg" data-caption="" data-size="normal" data-rawwidth="18" data-rawheight="26" class="content_image" width="18">
這個按鈕能讓你逐步查看 onClick() 函數(shù)的運行铭若,每次一行。當 DevTools 高亮顯示如下一行代碼時就停止:
if (inputsAreEmpty()) {
現(xiàn)在點擊“Step over next function call”按鈕
<img src="https://pic3.zhimg.com/v2-f8aa0d046dfbf1b1a28fdd031ee35e9e_b.jpg" data-caption="" data-size="normal" data-rawwidth="36" data-rawheight="20" class="content_image" width="36">
這會讓 DevTools 執(zhí)行 inputsAreEmpty() 而不進入它递览。注意 DevTools 跳過了幾行代碼叼屠,這是因為 inputsAreEmpty() 求值結(jié)果為 false,所以 if 語句的代碼塊沒有運行绞铃。
這就是逐步調(diào)試代碼的基本理念镜雨。如果你查看 get-started.js 中的代碼,會發(fā)現(xiàn) bug 可能在 updateLabel() 函數(shù)的某個位置儿捧。你不必逐行看完所有代碼荚坞,可以換用另一種斷點,在靠近該 bug 的位置暫停代碼運行菲盾。
步驟4:設(shè)置另一個斷點
代碼行斷點是最常見的斷點類型颓影。如果想在執(zhí)行到某一行代碼時暫停,就使用代碼行斷點懒鉴。試試吧:
查看 updateLabel() 中的最后一行代碼诡挂,如下所示:
label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
在代碼的左側(cè),你可以看到這行代碼的具體行數(shù):32临谱。點擊 32璃俗,DevTools 會在 32 上放置一個藍色圖標,表示在這里設(shè)置了一個代碼行斷點吴裤。這樣以來旧找,DevTools 總會在執(zhí)行這行代碼前暫停。
點擊“Resume script execution”按鈕
<img src="https://pic3.zhimg.com/v2-d70fc1ddc7b3737276ba2ef3deecaeb6_b.jpg" data-caption="" data-size="normal" data-rawwidth="26" data-rawheight="20" class="content_image" width="26">
這段腳本會持續(xù)執(zhí)行麦牺,直到到達你設(shè)置了斷點的那行代碼钮蛛。
查看 updateLabel() 中已執(zhí)行的代碼行鞭缭。DevTools 打印輸出 addend1,addend2 和 sum 的值魏颓。
Sum 的值看著很有問題岭辣,求值結(jié)果應(yīng)該是數(shù)字才對,但這里卻是字符串甸饱。這可能就是造成 bug 的原因沦童。
步驟5:檢查變量值
造成 bug 的另一個常見原因就是變量或函數(shù)產(chǎn)生了異常值。很多開發(fā)者會使用 console.log() 來查看值隨著時間變化的情況叹话,但使用 console.log() 枯燥又麻煩偷遗,而且沒有效率。究其原因有二驼壶,首先你可能需要手動編輯代碼氏豌,而且需要大量調(diào)用 console.log();其次热凹,你可能無法確定哪個變量和 bug 有關(guān)泵喘,所以你需要記錄很多變量。
DevTools 上有個替代 console.log() 的工具叫 Watch Expressions般妙,使用 Watch Expressions 能夠監(jiān)控變量值隨著時間的變化纪铺。正如其名,Watch Expressions 并不僅僅能監(jiān)控變量碟渺,你可以將任何有效的 JavaScript 表達式存儲在 Watch Expressions 中鲜锚。試試吧:
在 DevTools 上的“Source”面板上點擊“Watch”,然后這部分會展開止状。
點擊“Add Expression”
<img src="https://pic4.zhimg.com/v2-7067d5a4a4c50075cbc26c6b1f1adcc3_b.jpg" data-caption="" data-size="normal" data-rawwidth="20" data-rawheight="20" class="content_image" width="20">
輸入 typeof sum
按 Enter 鍵烹棉,DevTools 會顯示 typeof sum: "string"。冒號右邊的值就是你的 Watch Expression 的結(jié)果怯疤。
<img src="https://pic1.zhimg.com/v2-30af9a5e742674d281f2d365ff4f26c4_b.jpg" data-caption="" data-size="normal" data-rawwidth="800" data-rawheight="541" class="origin_image zh-lightbox-thumb" width="800" data-original="https://pic1.zhimg.com/v2-30af9a5e742674d281f2d365ff4f26c4_r.jpg">
和我們猜的一樣浆洗,sum 被處理成了字符串,而本應(yīng)是個數(shù)字集峦。這就是 demo 上的 bug 的來源伏社。
DevTools 中另一個能取代 console.log() 的工具是 Console,可以使用 Console 對任意 JavaScript 語句求值塔淤。很多開發(fā)者通常在調(diào) bug 時使用 Console 覆蓋變量值摘昌。在本教程這個例子中,Console 能幫你測試剛發(fā)現(xiàn)的 bug 的潛在修復方法高蜂。試試:
如果還沒打開 Console聪黎,按 Escape 鍵打開它,會在你的 DevTools 窗口底部打開备恤。
在 Console 中輸入 parseInt(addend1) + parseInt(addend2)
按 Enter 鍵稿饰,DevTools 會對語句求值锦秒,輸出 6,也就是開頭 Demo 中我們預期程序應(yīng)該輸出的結(jié)果喉镰。
<img src="https://pic1.zhimg.com/v2-05a303bb328e61b589887ad267c0d2ac_b.jpg" data-caption="" data-size="normal" data-rawwidth="800" data-rawheight="608" class="origin_image zh-lightbox-thumb" width="800" data-original="https://pic1.zhimg.com/v2-05a303bb328e61b589887ad267c0d2ac_r.jpg">
步驟6:應(yīng)用修復方法
確定一種修復 bug 的潛在方法后旅择,剩下的工作就是編輯代碼,嘗試修復侣姆,并重新運行 demo生真。不必離開 DevTools 界面就能應(yīng)用修復。你可以直接在 DevTools UI 里直接編輯 JavaScript 代碼捺宗。試試吧:
在 DevTools 的“Source”面板的代碼編輯器中柱蟀,用 var sum = parseInt(addend1) + parseInt(addend2) 替換 var sum = addend1 + addend2。就是當前暫停位置上面的那行代碼偿凭。
按 Command+S(Mac)或 Ctrl+S(Windows产弹,Linux)保存修改。代碼背景色變?yōu)榧t色弯囊,表示腳本已經(jīng)在 DevTools 中被修改。
點擊“Deactivate breakpoints”
<img src="https://pic3.zhimg.com/v2-2bea76830b3176ebc1e7c0dd41f1210a_b.jpg" data-caption="" data-size="normal" data-rawwidth="19" data-rawheight="17" class="content_image" width="19">
它變?yōu)樗{色表示正處于活動狀態(tài)胶果。如果這樣設(shè)置匾嘱,DevTools 會忽略你設(shè)置的任何斷點。
點擊“ Resume script execution”
<img src="https://pic1.zhimg.com/v2-c08b0ef2429def9115ff6272c35642fc_b.jpg" data-caption="" data-size="normal" data-rawwidth="26" data-rawheight="20" class="content_image" width="26">
可以用不同的值試試吧早抠,現(xiàn)在 demo 應(yīng)該能正確地計算出 sum 值了霎烙。
注意:該工作流程只對運行在瀏覽器中的代碼應(yīng)用修正。它不會為所有運行你的頁面的用戶修正代碼蕊连。要想實現(xiàn)該目的悬垃,需要修正運行在提供頁面的服務(wù)器上的代碼。
以上就是在 DevTools 中調(diào)試 JavaScript bug 的基礎(chǔ)知識甘苍,本文只介紹了兩種設(shè)置斷點的方法尝蠕,此外還有不少很多其它方法,比如:
僅在滿足你指定的條件時觸發(fā)的條件斷點载庭。
發(fā)生已捕獲或未捕獲異常時觸發(fā)的斷點看彼。
當請求的網(wǎng)址和你提供的子字符串匹配時觸發(fā)的 XHR 斷點。
更多使用 DevTools 調(diào)試 bug 的知識囚聚,可以查看官方文檔靖榕。