原链接:https://www.zhihu.com/question/35667558/answer/530643532
编程新手刚开始查找和修复 bug 还是比较困难的,你可能会随机使用 console.log(),试图让代码正确运行。看了本文再也不用这么干了!
下面就教你一个调 bug 的正确姿势。你会学习如何使用 Chrome 开发者工具设置断点,逐步调试代码。这种工作方法能让你查找和修复 bug 的效率大幅提高。
虽然这篇教程展示的是怎么调试一个具体的 bug,但是整体工作思路对调试任何类型的 JavaScript bug 都是有指导意义的。
步骤1:重现 bug
调试 bug 的第一步就是重现 bug。所谓“重现 bug”就意味着要找到一系列持续导致出现这个 bug 的操作。你可能需要多次重现 bug,所以尽可能地减少不必要的步骤。
按照如下指令来重现本教程需要修复的 bug。
这是我们本教程会使用的网页,确保以新的标签:Demo: Get Started Debugging JavaScript with Chrome DevTools
在 demo 中,在“Number 1”文本框中输入 5
在“Number 2”文本框中输入数字 2
点击“Add Number 1 and Number 2”按钮
查看输入和按钮下方的标签,显示 5 + 1 = 51.
这不,bug 来了,这里结果明显错了,应该是 6。这就是你要修复的 bug。
步骤2:使用断点暂停代码
Chrome 开发者工具(以下简称 DevTools)能让你在代码运行期间暂停代码,并检查此刻所有变量的值。暂停代码的工具叫做 Breakpoint。试试吧:
回到 demo,按 Command+Option(Mac)或 Ctrl+shift+I(Windows,Linux)打开DevTools
点击“Source”标签
点击“Event Listener Breakpoints”(事件监听断点)展开该部分。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 事件上设置一个基于事件的断点。每当节点被点击,并且节点有 click 处理程序时,DevTools 就会在该节点的 click 处理程序的第一行代码处自动暂停。
这里还是要推荐下小编的web前端学习群:867726593,不管你是小白还是大牛,小编我都欢迎,不定期分享干货,包括小编自己整理的一份最新的web前端资料和0基础入门教程,欢迎初学和进阶中的小伙伴。在不忙的时间我会给大家解惑。
步骤3:逐步调试代码
导致出现 bug 的一个常见原因就是脚本运行顺序不正确。逐步调试代码能让你过一遍你的代码运行状况,每次一行,准确找出哪里没有按照预期的顺序执行。试试:
在 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() 函数的运行,每次一行。当 DevTools 高亮显示如下一行代码时就停止:
if (inputsAreEmpty()) {
现在点击“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 执行 inputsAreEmpty() 而不进入它。注意 DevTools 跳过了几行代码,这是因为 inputsAreEmpty() 求值结果为 false,所以 if 语句的代码块没有运行。
这就是逐步调试代码的基本理念。如果你查看 get-started.js 中的代码,会发现 bug 可能在 updateLabel() 函数的某个位置。你不必逐行看完所有代码,可以换用另一种断点,在靠近该 bug 的位置暂停代码运行。
步骤4:设置另一个断点
代码行断点是最常见的断点类型。如果想在执行到某一行代码时暂停,就使用代码行断点。试试吧:
查看 updateLabel() 中的最后一行代码,如下所示:
label.textContent = addend1 + ' + ' + addend2 + ' = ' + sum;
在代码的左侧,你可以看到这行代码的具体行数:32。点击 32,DevTools 会在 32 上放置一个蓝色图标,表示在这里设置了一个代码行断点。这样以来,DevTools 总会在执行这行代码前暂停。
点击“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">
这段脚本会持续执行,直到到达你设置了断点的那行代码。
查看 updateLabel() 中已执行的代码行。DevTools 打印输出 addend1,addend2 和 sum 的值。
Sum 的值看着很有问题,求值结果应该是数字才对,但这里却是字符串。这可能就是造成 bug 的原因。
步骤5:检查变量值
造成 bug 的另一个常见原因就是变量或函数产生了异常值。很多开发者会使用 console.log() 来查看值随着时间变化的情况,但使用 console.log() 枯燥又麻烦,而且没有效率。究其原因有二,首先你可能需要手动编辑代码,而且需要大量调用 console.log();其次,你可能无法确定哪个变量和 bug 有关,所以你需要记录很多变量。
DevTools 上有个替代 console.log() 的工具叫 Watch Expressions,使用 Watch Expressions 能够监控变量值随着时间的变化。正如其名,Watch Expressions 并不仅仅能监控变量,你可以将任何有效的 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 的结果。
<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 被处理成了字符串,而本应是个数字。这就是 demo 上的 bug 的来源。
DevTools 中另一个能取代 console.log() 的工具是 Console,可以使用 Console 对任意 JavaScript 语句求值。很多开发者通常在调 bug 时使用 Console 覆盖变量值。在本教程这个例子中,Console 能帮你测试刚发现的 bug 的潜在修复方法。试试:
如果还没打开 Console,按 Escape 键打开它,会在你的 DevTools 窗口底部打开。
在 Console 中输入 parseInt(addend1) + parseInt(addend2)
按 Enter 键,DevTools 会对语句求值,输出 6,也就是开头 Demo 中我们预期程序应该输出的结果。
<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:应用修复方法
确定一种修复 bug 的潜在方法后,剩下的工作就是编辑代码,尝试修复,并重新运行 demo。不必离开 DevTools 界面就能应用修复。你可以直接在 DevTools UI 里直接编辑 JavaScript 代码。试试吧:
在 DevTools 的“Source”面板的代码编辑器中,用 var sum = parseInt(addend1) + parseInt(addend2) 替换 var sum = addend1 + addend2。就是当前暂停位置上面的那行代码。
按 Command+S(Mac)或 Ctrl+S(Windows,Linux)保存修改。代码背景色变为红色,表示脚本已经在 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">
它变为蓝色表示正处于活动状态。如果这样设置,DevTools 会忽略你设置的任何断点。
点击“ 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">
可以用不同的值试试吧,现在 demo 应该能正确地计算出 sum 值了。
注意:该工作流程只对运行在浏览器中的代码应用修正。它不会为所有运行你的页面的用户修正代码。要想实现该目的,需要修正运行在提供页面的服务器上的代码。
以上就是在 DevTools 中调试 JavaScript bug 的基础知识,本文只介绍了两种设置断点的方法,此外还有不少很多其它方法,比如:
仅在满足你指定的条件时触发的条件断点。
发生已捕获或未捕获异常时触发的断点。
当请求的网址和你提供的子字符串匹配时触发的 XHR 断点。
更多使用 DevTools 调试 bug 的知识,可以查看官方文档。
网友评论