前面讲了那么多基础性知识性的东西,本节我们来讲讲实战的一部分--代码调试。

# debug--调试

通常来说,我们写代码的时候主要通过两种方式进行调试:代码中调试、浏览器中调试。

# 代码中调试

在代码中调试,其实说白了也就常用的alert()consoledebugger等输出和断点。

# alert

alert()会在窗口中显示一个警告对话框,上面显示有指定的文本内容以及一个“确定”按钮。

使用alert()需要注意的是:

  1. alert()会阻塞进程。
  2. alert(param)param只能是numberstring类型或者它们组成的数组。

如果我们运行以下代码:

alert(["123", "123", 32, { 1: 123 }]);

会得到这样的结果: image

# console

console的使用,大概是本骚年最常用的一个吧。

很多人喜欢打断点来 debug,不过我用得最多的还是console.log()。当然这通常是自己调试自己的代码,如果说里面用到一些别人的库、调试其他人的问题的时候,或许打断点会更适合一些。

console常用的几个方法有:

  • console.log():打印字符串,以及对象、变量什么的都可以。
  • console.info():打印以感叹号字符开始的信息,使用方法和log相同。
  • console.error():打印一条错误信息。
  • console.dir():打印一条以三角形符号开头的语句,可以点击三角展开查看对象的属性。

    console.dir()常用于打印DOM元素的属性

其他的可以参考Console | MDN (opens new window)

console适用于大致已定位到哪里出了问题,然后在某些关键点输出。这是个人的感觉,其实更多只是习惯问题吧。

自从浏览器支持 ES6 之后,本人就很喜欢这样输出了:

// 这样可以顺便把变量名也打印出来
console.log({ data, list, state });

# debugger

debugger语句调用任何可用的调试功能,例如设置断点。 如果没有调试功能可用,则此语句不起作用。
debugger被调用时, 执行暂停在debugger语句的位置。就像在脚本源代码中的断点一样。

我基本很少用到debugger,不过据说在node.js中,因为木有浏览器自带的断点,使用debugger来调试也是很方便的(可惜自己做来做去,还是主打 PC 端应用就是了)。

还有,使用完之后,发布前记得注释或者删除掉噢。

# 浏览器(Chrome)调试

浏览器中调试功能又多又方便(主要是在 Chrome 下),大家可以参考下一些文章。前面章节有简单介绍过,这里讲一下用得比较多的,后面也会给到一些参考文章。

# DevTools

我们先看看 Chrome 提供的开发者工具:
image

跟上次一样,我们从左往右讲起:

  1. 箭头按钮:用于在页面选择一个元素来审查和查看它的相关信息。
  2. 设备图标:点击它可以切换到不同的终端(移动端和 PC 端)进行开发模式。可以选择不同的移动终端设备,同时可以选择不同的尺寸比例。常用的移动端页面调试,还能通过配置User agent来模拟终端环境。
  3. Elements:用来查看、修改页面上的元素,包括DOM标签,以及css样式的查看,修改,还有相关盒模型的图形信息。
  4. Console:用于打印和输出相关的命令信息,源代码定位等等。
  5. SourcesSources下的Sources查看浏览器页面中的源文件(html/js/img/css等),点击下面的{}大括号可以将代码转成可读格式,同时可给js文件添加上断点。Sources下的Snippets可以添加文件片段,可在浏览器中运行。
  6. Network:可以看到所有的资源请求,包括网络请求、静态资源(htmlcssjs、图片等)文件请求,常用于调试网络请求。

剩下的功能或许用得不是特别多,可以了解下(本人了解不多,或许不一定准确):

  1. Performance:查看页面在浏览器运行时的性能表现,如 CPU\GPU 执行时间与内存占用等。
  2. Memory:似乎是内存泄漏分析相关的功能?
  3. Application:会列出所有的资源,以及 HTML5 的 Database 和 LocalStore 等,你可以对存储的内容编辑和删除。
  4. Security:查看网站的安全性,有效证书等。
  5. Audits:会针对目前网页提出若干条优化的建议,这些建议分为两大类,一类是网络加载性能,另一类是界面性能。

# 打断点

# 1. 代码断点

常用的浏览器代码断点,在Sources面板js文件行号处设置断点,如图我们下了个断点:
image

这里我们在请求发起的位置打了个断点,每次我们在搜索输入框输入的时候,都会发送请求,触发 debug 模式。

这里除了常规断点外, 还有个条件断点(右键 -> conditional breakpoint), 在设置的条件为true时才会断电, 在循环中需要断点时比较有用。断点后可以查看堆栈、变量。

# 2. 事件断点

元素上事件断点:某一事件/某类事件,从Elements > Event Listeners中进行。

# 3. DOM 断点

一般是DOM结构改变时触发。有时候我们需要监听某个DOM被修改情况,而不关心是哪行代码做的修改(也可能有多处都会对其做修改),可以直接在DOM上设置断点。

在元素审查的Elements标签页中在某个元素上右键菜单里可以设置三种不同情况的断点:

  • 子节点修改
  • 自身属性修改
  • 自身节点被删除

# 4. XHR 断点

右侧调试区有一个XHR Breakpoints,点击+ 并输入URL包含的字符串,即可监听该URLAjax请求,输入内容就相当于URL的过滤器。
一旦XHR调用触发时就会在request.send()的地方中断。

# 5. 全局事件断点

对事件发生时断点,不会限定在元素上,只要是事件发生,并且有handler就断点。
还可以对resizeajaxsetTimeout/setInterval断点。

上面这些断点本骚年都用得不是很多,所以也不能提供很好的说明。
更多详细内容,可以参考《页面制作之调试工具》 (opens new window),里面通过动图讲述了一些断点是如何添加的。

# 关于 debug 的一点心得

# debug 样式

样式的调试需要有个前提,就是对一些样式属性有很好的认识和理解,尤其涉及盒子模型、display和定位等。
样式的规则除了一些基本的逻辑能遵循(可参考前面文章《3.HTML 和 CSS》),更多的则是丰富的经验,多写、多练。

在此之外,一般样式的 debug 逻辑大概会是这样:

  1. 样式是否生效。
  2. 文件、相关样式代码是否加载。
  3. 是否被其他样式覆盖(优先级问题)。

常见的有上面的问题,除此之外,大部分都是没使用合理的style了吧。

image
如上图,一般我们会在选中对应的元素后,从上往下来找到生效(或不生效)的样式,同时也可以定位到对应的源文件。

这里面如果是本地环境调试的话,在source map的支持下,我们甚至可以直接在浏览器中修改源文件,保存生效。具体配置和操作可以参考将预处理代码映射到源代码 (opens new window)

# debug JS

JS 的调试,像上面说过的,一般分为输出和打断点两种。

一般 JS 的 debug 逻辑,未按预期执行会有这样的原因:代码未执行到理想的位置。

这时候我们要思考这样的问题:

  1. 为事件触发执行 -> 检测事件是否被触发。
  2. 在函数中执行 -> 检测函数是否被调用。
  3. 在判断语句中执行 -> 检测判断是否正确。

我们可以在这些地方进行输出,或者打下断点:

  1. 事件触发的地方。
  2. 函数调用过程。
  3. 判断语句(if等)。

以上是类似的推导逻辑,我们在写代码时,会有一个预期的执行顺序和期望,如果说不生效,则我们可以:

  • 从前往后执行步骤,看在哪一步分了岔路
  • 从后往前打下断点,看在哪一步走丢了

其实最重要的是思路需要清晰,如果说你连自己要做的功能,逻辑还没理清楚的话,编写的代码质量不会高,同时调试性能也会随着下降。

# 参考

# 结束语

这一节我们主要基于 Chrome 浏览器,大致讲了一些开发者工具的功能。调试是很重要的一步,每一次 debug 我们都要吸取经验,总结教训。不管是 CSS 还是 JS 的调试,经验的积累都是很需要的,同时也能提高我们写代码的质量。

部分文章中使用了一些网站的截图,如果涉及侵权,请告诉我删一下谢谢~
温馨提示喵