很少有人能一下子就写出完全没有问题的代码。工作良好的程序,都是经过一遍遍的反复测试运行、发现问题、剔除问题(也就是我们所说的找Bug和修Bug)过后的产物,经过了这一过程,程序才能最终达到一个相对稳定的状态。
对编程初学者来说,可能都有过这样的经历:你按照网上或书本上的教程文章,在自己的代码编辑器中一字一句的抄写下教程中的代码,然后满怀激动的运行代码,期待出现和教程中一模一样的输出结果。然而,一大坨错误信息向你扑面而来......你手足无措,口中念念有词:怎么肥事,怎么肥事......
我遇到过很多程序员(不管是初学的或已从业多年的),一看到代码报错,第一反应就是:代码报错了!怎么办?怎么解决?!谁来帮帮我......
好吧,大可不必惊慌,冷静一下。
第一,你不是在写自爆程序。
第二,你这是在赤裸裸的无视放在眼前的问题解决方法!
这些扑面而来的错误信息可不是一堆无意义的文字,大多数时候,它们明确的显示了错误产生的位置、导致错误的原因、甚至会有错误的修复方式。你需要的是仔细阅读,它们是你的小天使,为你指出了一条修复问题的明路。
学会根据错误信息来定位代码错误
下面我们就来动手,试着执行一下这段有问题的代码:
let a = 10;
let b = 2;
let c = a / d;
console.log(c);
执行这段代码,如果是在浏览器中执行,那么可能结果会是这样的:
或者是使用命令行的方式在Node.js下运行,则看起来结果是这样的:
无论是浏览器还是Node.js,出现的报错信息中,都给出了一段错误的描述信息:
ReferenceError: d is not defined
有的程序员说,我不看报错信息,是因为我看到英语就头晕。好吧,帮你翻译一下:
引用错误:d未定义
说的挺明显了,代码中的变量d
没有经过定义就被使用了。还好我们这次的代码比较少,我们一眼就找到使用了这个未定义的变量d
的地方:
let c = a / d;
嗯,这也许是你打代码的时候不小心的输入错误,这个地方应该是前面定义的变量b
,而不是d
。哈哈,找到原因啦,改正改正。
如果我们的代码有很多呢,从几千几万行的代码里去找这段错误代码,如何快速定位?还是从错误信息这里着手!
我们再回头看浏览器里的错误信息:
在上面的错误信息里,原来还包含着错误发生的代码文件来源以及错误在这个代码文件中所在的行数(test1.js: 3),而且你点击这个文件名,就可以直接进入到这个代码文件中查看,如下:
错误被精准的定位,这方便的简直就是送货上门了。
相应的,命令行下的错误信息也是比较清楚的,也给你指明了错误所在的文件路径、哪一行那一列:
如果你正在使用VSCode编写和运行代码的话,可以进一步享受到它带来的便利。在VSCode的菜单中选择“调试”
>"开始调试"
来运行你的代码,则你的错误代码会随之被高亮显示:
怎么样?神器在手,编码无忧啊!
学会单步调试你的代码
上面我们讨论的内容,是如何根据错误信息,定位明显的错误。但是,正所谓:明枪易躲,暗箭难防。还有大量根本就是不会报错的错误,比如由于代码逻辑或是js弱类型转换赋值不正确导致的错误,它们不会造成代码报错,但是却能使你的程序得不到正确的运行结果。
没有报错信息的指引,我们该怎么来寻找错误根源?
一种比较古老的方式,是使用console或alert在你的代码的每一个关键部位打印出输入或输出结果,然后在代码执行的时候观察打印出来的内容,判断代码到底是在哪个地方产生了预期之外的结果。这种方法现在还是会被采用,但是用起来还是有点费劲的。随着浏览器和支持Node.js的代码编辑器的调试功能越来越好用,它已经可以退居二三四五线了。
另一种方式,就是借助浏览器和代码编辑器的断点调试功能,实现对我们的代码进行单步执行。这种调试方式可以让我们清晰的观察到代码的执行流程步骤,执行过程中每一个变量的值,以及变量值的变化情况。
人生苦短,快用断点调试。
接下来我们来看一下如何分别在浏览器和编辑器里单步调试我们的代码。我们还是使用之前的教程里的简易计算器代码吧。
在VSCode中打开这个简易计算器的代码目录,并打开 server.js
文件,然后从VSCode菜单中选择“调试”
>"开始调试"
,这样,你的代码就运行在调试模式了。
如果期间弹出这样一个让你配置launch.json
的界面,请将这个launch.json
里的program
的值改成${workspaceFolder}/server.js
,因为我们的Node.js程序主入口文件是server.js
:
进入调试模式的VSCode界面就像如下的样子:
接下来,在浏览器里输入 http://localhost:8888/calculator.html,打开我们的计算器页面,并打开浏览器的开发者工具,通过开发者工具的Source
选项卡,找到我们当前页面calculator.html
的网页源代码:
在浏览器开发者工具中打开的网页代码界面上,我们可以点击JavaScript代码的行号部分,设置断点(顾名思义,表示代码执行到这里会暂时停下来):
我们在calc
函数里面设置了3个断点,如果代码执行并进入calc
函数,则会依次在这个三个断点处停下来。如果在计算器界面上输入些简单数值并点击计算按钮,我们可以发现调试界面会高亮显示当前代码暂停的位置:
接着,我们可以通过调试界面右侧上面的一排按钮,控制代码的执行,主要功能有:
- 继续执行,直到遇到下一个断点
- 继续执行下一行代码
- 跳入到当前代码行上正在调用的函数内部
- 跳出当前函数
- 启用/禁用所有断点
- 启用/禁用代码在发生异常(Exception)的时候进行暂停
在左边的代码窗口中,你可以看到执行过的代码行右侧,显示了各变量的值;如果将鼠标悬停在变量名上,更可以看到该变量的详细内容信息。这样,你就可以轻易的判断出当前执行结果是否如你预期。
在调试工具的右侧面板上,提供了更多功能选项,用于对例如变量、Ajax请求、DOM事件、以及各种浏览器功能API的调用进行跟踪,使你对程序的执行细节有更深入的了解和掌控,感兴趣的朋友可以自行挖掘。
到此,我们知道怎么调试浏览器里的代码了,回过头来再看在VSCode里调试Node.js后端代码,就觉得不那么陌生了,因为非常的相似。同样在你想暂停的代码行号前点击,设置好断点,并将编辑器的左侧面板切换到调试界面:
然后,重新去浏览器那边的计算器网页中进行一次计算操作,当点击计算按钮的时候,网页代码中会通过Ajax调用后端的/calc
服务,因此,VSCode中的代码就会在之前设置的断点处暂停下来,随之你可以通过编辑器顶部的调试工具栏上的按钮,进行和浏览器中类似的单步调试啦!
总结
熟练运用查看报错信息以及代码调试功能,可以让你对代码的理解变得更加深刻,你编码的工作效率也会随之提升。遇到问题,不要再胡乱的猜测问题的原因啦,赶紧拿起工具,去调试一番吧!
正确使用工具,加速你的生产力。
欢迎关注一斤代码的系列课程《从编程小白到全栈开发》