前面讲了那么多基础性知识性的东西,本节我们来讲讲实战的一部分--代码调试。
# debug--调试
通常来说,我们写代码的时候主要通过两种方式进行调试:代码中调试、浏览器中调试。
# 代码中调试
在代码中调试,其实说白了也就常用的alert()
、console
、debugger
等输出和断点。
# alert
alert()
会在窗口中显示一个警告对话框,上面显示有指定的文本内容以及一个“确定”按钮。
使用alert()
需要注意的是:
alert()
会阻塞进程。alert(param)
中param
只能是number
、string
类型或者它们组成的数组。
如果我们运行以下代码:
alert(["123", "123", 32, { 1: 123 }]);
会得到这样的结果:
# 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 提供的开发者工具:
跟上次一样,我们从左往右讲起:
- 箭头按钮:用于在页面选择一个元素来审查和查看它的相关信息。
- 设备图标:点击它可以切换到不同的终端(移动端和 PC 端)进行开发模式。可以选择不同的移动终端设备,同时可以选择不同的尺寸比例。常用的移动端页面调试,还能通过配置
User agent
来模拟终端环境。 Elements
:用来查看、修改页面上的元素,包括DOM
标签,以及css
样式的查看,修改,还有相关盒模型的图形信息。Console
:用于打印和输出相关的命令信息,源代码定位等等。Sources
:Sources
下的Sources
查看浏览器页面中的源文件(html/js/img/css
等),点击下面的{}
大括号可以将代码转成可读格式,同时可给js
文件添加上断点。Sources
下的Snippets
可以添加文件片段,可在浏览器中运行。Network
:可以看到所有的资源请求,包括网络请求、静态资源(html
、css
、js
、图片等)文件请求,常用于调试网络请求。
剩下的功能或许用得不是特别多,可以了解下(本人了解不多,或许不一定准确):
Performance
:查看页面在浏览器运行时的性能表现,如 CPU\GPU 执行时间与内存占用等。Memory
:似乎是内存泄漏分析相关的功能?Application
:会列出所有的资源,以及 HTML5 的 Database 和 LocalStore 等,你可以对存储的内容编辑和删除。Security
:查看网站的安全性,有效证书等。Audits
:会针对目前网页提出若干条优化的建议,这些建议分为两大类,一类是网络加载性能,另一类是界面性能。
# 打断点
# 1. 代码断点
常用的浏览器代码断点,在Sources
面板js
文件行号处设置断点,如图我们下了个断点:
这里我们在请求发起的位置打了个断点,每次我们在搜索输入框输入的时候,都会发送请求,触发 debug 模式。
这里除了常规断点外, 还有个条件断点(右键 -> conditional breakpoint), 在设置的条件为true
时才会断电, 在循环中需要断点时比较有用。断点后可以查看堆栈、变量。
# 2. 事件断点
元素上事件断点:某一事件/某类事件,从Elements > Event Listeners
中进行。
# 3. DOM 断点
一般是DOM
结构改变时触发。有时候我们需要监听某个DOM
被修改情况,而不关心是哪行代码做的修改(也可能有多处都会对其做修改),可以直接在DOM
上设置断点。
在元素审查的Elements
标签页中在某个元素上右键菜单里可以设置三种不同情况的断点:
- 子节点修改
- 自身属性修改
- 自身节点被删除
# 4. XHR 断点
右侧调试区有一个XHR Breakpoints
,点击+
并输入URL
包含的字符串,即可监听该URL
的Ajax
请求,输入内容就相当于URL
的过滤器。
一旦XHR
调用触发时就会在request.send()
的地方中断。
# 5. 全局事件断点
对事件发生时断点,不会限定在元素上,只要是事件发生,并且有handler
就断点。
还可以对resize
、ajax
、setTimeout/setInterval
断点。
上面这些断点本骚年都用得不是很多,所以也不能提供很好的说明。
更多详细内容,可以参考《页面制作之调试工具》 (opens new window),里面通过动图讲述了一些断点是如何添加的。
# 关于 debug 的一点心得
# debug 样式
样式的调试需要有个前提,就是对一些样式属性有很好的认识和理解,尤其涉及盒子模型、display
和定位等。
样式的规则除了一些基本的逻辑能遵循(可参考前面文章《3.HTML 和 CSS》),更多的则是丰富的经验,多写、多练。
在此之外,一般样式的 debug 逻辑大概会是这样:
- 样式是否生效。
- 文件、相关样式代码是否加载。
- 是否被其他样式覆盖(优先级问题)。
常见的有上面的问题,除此之外,大部分都是没使用合理的style
了吧。
如上图,一般我们会在选中对应的元素后,从上往下来找到生效(或不生效)的样式,同时也可以定位到对应的源文件。
这里面如果是本地环境调试的话,在source map
的支持下,我们甚至可以直接在浏览器中修改源文件,保存生效。具体配置和操作可以参考将预处理代码映射到源代码 (opens new window)。
# debug JS
JS 的调试,像上面说过的,一般分为输出和打断点两种。
一般 JS 的 debug 逻辑,未按预期执行会有这样的原因:代码未执行到理想的位置。
这时候我们要思考这样的问题:
- 为事件触发执行 -> 检测事件是否被触发。
- 在函数中执行 -> 检测函数是否被调用。
- 在判断语句中执行 -> 检测判断是否正确。
我们可以在这些地方进行输出,或者打下断点:
- 事件触发的地方。
- 函数调用过程。
- 判断语句(
if
等)。
以上是类似的推导逻辑,我们在写代码时,会有一个预期的执行顺序和期望,如果说不生效,则我们可以:
- 从前往后执行步骤,看在哪一步分了岔路
- 从后往前打下断点,看在哪一步走丢了
其实最重要的是思路需要清晰,如果说你连自己要做的功能,逻辑还没理清楚的话,编写的代码质量不会高,同时调试性能也会随着下降。
# 参考
- 《前端 chrome 浏览器调试总结》 (opens new window)
- Chrome DevTools Overview (opens new window)
- 《页面制作之调试工具》 (opens new window)
# 结束语
这一节我们主要基于 Chrome 浏览器,大致讲了一些开发者工具的功能。调试是很重要的一步,每一次 debug 我们都要吸取经验,总结教训。不管是 CSS 还是 JS 的调试,经验的积累都是很需要的,同时也能提高我们写代码的质量。