使用Chrome调试JavaScript的断点设置和调试技巧


Posted in Javascript onDecember 16, 2014

你是怎么调试 JavaScript 程序的?最原始的方法是用 alert() 在页面上打印内容,稍微改进一点的方法是用 console.log() 在 JavaScript 控制台上输出内容。嗯~,用这两种土办法确实解决了很多小型 JavaScript 脚本的调试问题。不过放着 Chrome 中功能越发强大的开发者工具不用实在太可惜了。本文主要介绍其中的 JavaScript断点设置和调试功能,也就是其中的 Sources Panel(以前叫 Scripts)。如果你精通 Eclipse 中的各种 Java 调试技巧,那么这里的概念都是类似。写作本文时使用的 Chrome 版本为 25.0.1364.172。

基本环境

使用Chrome调试JavaScript的断点设置和调试技巧

SourcesPanel 的左边是内容源,包括页面中的各种资源。其中,又分 Sources 和 Content scripts。Sources 就是页面本身包含的各种资源,它是按照页面中出现的域来组织的,这是我们要关注的。异步加载的 js 文件,在加载后也会出现在这里的。Content scripts 是 Chrome 的一种扩展程序,它是按照扩展的ID来组织的,这类扩展实际也是嵌入在页面中的资源,它们也可以读写DOM。编写、调试这类扩展的开发者才要关心它们,如果你的浏览器没安装任何扩展,那么Content scripts 就看不到任何东西。

Sources Panel 的中间主区域用于展示左边资源文件的内容。

Sources Panel 的右边是调试功能区,最上面的一排按钮分别是暂停/继续、单步执行、单步跳入、单步跳出、禁用/启用所有断点。下面是各种具体的功能区。稍后介绍。

注意,左右两边的区域默认可能收缩在两侧没有显示出来,点击两侧的伸缩按钮使用Chrome调试JavaScript的断点设置和调试技巧使用Chrome调试JavaScript的断点设置和调试技巧展示出来。左边区域展示出来时默认是自动收缩状态,点击旁边的 pin 按钮使用Chrome调试JavaScript的断点设置和调试技巧就不会缩回去了。

最下面还有一些功能按钮很有用。

在源代码上设置断点

通过左边的内容源,打开对应的 JavaScript 文件,鼠标点击文件的行号就可以设置和删除断点。添加的每个断点都会出现在右侧调试区的 Breakpoints 列表中,点击列表中断点就会定位到内容区的断点上。如果你有多个文件、多个断点的话,利用Breakpoints 列表中的断点快速定位非常方便。

使用Chrome调试JavaScript的断点设置和调试技巧

对于每个已添加的断点都有两种状态:激活和禁用。刚添加的断点都是激活状态,禁用状态就是保留断点但临时取消该断点功能。在Breakpoints 列表中每个断点前面都有一个复选框,取消选中就将禁用该断点。断点位置的右键菜单中也可以禁用断点。也可以在右侧功能区上面使用Chrome调试JavaScript的断点设置和调试技巧按钮临时禁用所有已添加的断点,再点一下恢复原状态。

条件断点:在断点位置的右键菜单中选择“Edit Breakpoint...”可以设置触发断点的条件,就是写一个表达式,表达式为 true 时才触发断点。查看断点的环境调用栈(Call Stack):在断点停下来时,右侧调试区的 Call Stack 会显示当前断点所处的方法调用栈,比如有一个函数 g() 其中又调用了函数 f() ,而我在 f() 中设置了一个断点,那么我在 console 中执行函数 g() 的时候会触发断点,其调用栈显示如下:

使用Chrome调试JavaScript的断点设置和调试技巧

最上面是 f(),然后是 g()。调用栈中的每一层叫做一个 frame,点击每个 frame 可以跳到该 frame 的调用点上。

使用Chrome调试JavaScript的断点设置和调试技巧

此外,还可以在 frame 上用右键菜单重新开始执行当前 frame,也就是从该 frame 的开始处执行。比如在函数 f() 的 frame 上 Restart Frame, 断点就会跳到 f() 的开头重新执行,context 中的变量值也会还原。这样结合变量修改和编辑代码等功能,就可以在当前 frame 中反复进行调试,而不用刷新页面重新触发断点了。查看变量

使用Chrome调试JavaScript的断点设置和调试技巧

Call Stack 列表的下方是 Scope Variables 列表,在这里可以查看此时局部变量和全局变量的值。执行选择的代码

使用Chrome调试JavaScript的断点设置和调试技巧

在断点调试时,可以用鼠标选择想要查看的变量或表达式,然后右键菜单执行“Evaluate in Console”,就可以看到该表达式的当前的值了。中断下次要执行的 JavaScript 语句右侧调试区的上面的“中断/继续”按钮还有一个功能,在没有触发断点时,点一下这个按钮就会进入“准备”中断的状态,页面下一次执行 JavaScript 语句时会自动中断,比如触发了一个点击动作时会执行的代码。临时修改 JavaScript 代码通常我们在调试代码时习惯:修改代码→刷新页面→重新检查,这么一个循环。但其实 Chrome 中可以临时修改 JS 文件中的内容,保存(Ctrl+S)就可以立即生效,结合 Console 等功能就可以立即重新调试了。但注意这个修改是临时的,刷新页面修改就没了。

异常时断点

在界面下方能看到使用Chrome调试JavaScript的断点设置和调试技巧按钮,它是设置程序运行时遇到异常时是否中断的开关。点击该按钮会在3种状态间切换:

使用Chrome调试JavaScript的断点设置和调试技巧默认遇到异常不中断

使用Chrome调试JavaScript的断点设置和调试技巧遇到所有异常都会中断,包括已捕获的情况

使用Chrome调试JavaScript的断点设置和调试技巧仅在出现未捕获的异常时才中断

主要解释一下状态2和状态3的区别

try{
throw 'a exception';
}catch(e){
console.log(e);
}

上面 try 里面的代码会遇到异常,但是后面的 catch 代码能够捕获该异常。如果是所有异常都中断,那么代码执行到会产生异常的 throw 语句时就会自动中断;而如果是仅遇到未捕获异常才中断,那么这里就不会中断。一般我们会更关心遇到未捕获异常的情况。

在 DOM 元素上设置断点

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

使用Chrome调试JavaScript的断点设置和调试技巧

如图所见,在元素审查的 Elements Panel 中在某个元素上右键菜单里可以设置三种不同情况的断点:子节点修改自身属性修改自身节点被删除选中之后,Sources Panel 中右侧的 DOM Breakpoints 列表中就会出现该 DOM 断点。一旦执行到要对该 DOM 做相应修改时,代码就会在那里停下来,如下图所示。使用Chrome调试JavaScript的断点设置和调试技巧

XHR 断点

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

按事件类型触发断点

右侧调试区的Event Listener 列表,这里列出了各种可能的事件类型。勾选对应的事件类型,当触发了该类型的事件的 JavaScript 代码时就会自动中断。

调试快捷键

使用Chrome调试JavaScript的断点设置和调试技巧所有开发工具中的快捷键都可以在界面右下角的设置中查到。断点调试时一般用的是 F8、F10、F11或 Shitf+F11,但在 Mac OS 上 F10 等功能键可能与系统默认的快捷键冲突。没关系,它们分别可以用 Cmd+/ 、Cmd+'、Cmd+; 、Shift+Cmd+; 代替。//@ sourceURL 给 eval 出来的代码命名有时候一些非常动态的代码是以字符串的形式通过 eval() 函数在当前 Javascript context 中创建出来,而不是作为一个独立的 js 文件加载的。这样你在左边的内容区就找不到这个文件,因此很难调试。其实我们只要在 eval 创建的代码末尾添加一行 “//@ sourceURL=name“就可以给这段代码命名(浏览器会特殊对待这种特殊形式的注释),这样它就会出现在左侧的内容区了,就好像你加载了一个指定名字的 js 文件一样,可以设置断点和调试了。下图中,我们通过 eval 执行了一段代码,并利用sourceURL 将它命名为dynamicScript.js ,执行后左侧内容区就出现了这个“文件”,而它的内容就是 eval 的中的内容。使用Chrome调试JavaScript的断点设置和调试技巧还可以看看这个给动态编译出来的CoffeeScript 代码命名的示例:

var coffee = CoffeeScript.compile(code.value)+ "//@ sourceURL=" + (evalName.value || "Coffeeeeeeee!");
eval(coffee);

实际上,//@ sourceURL 不仅仅可以用在 eval 的代码中,任何 js 文件、甚至是 Javascript Console 输入的代码都可以用,效果一样!格式化代码(Pretty Print)使用Chrome调试JavaScript的断点设置和调试技巧按钮用于把杂乱的代码重新格式化为漂亮的代码,比如一些已被压缩的 js 文件基本没法看、更没法调试。点一下格式化,再点一下就取消格式化。使用Chrome调试JavaScript的断点设置和调试技巧美化前
使用Chrome调试JavaScript的断点设置和调试技巧美化后参考资料:Chrome Developer Tools 官方文档

Javascript 相关文章推荐
jquery 图片上传按比例预览插件集合
May 28 Javascript
js获取height和width的方法说明
Jan 06 Javascript
使用js dom和jquery分别实现简单增删改
Sep 11 Javascript
js控制文本框只输入数字和小数点的方法
Mar 10 Javascript
JavaScript实现向OL列表内动态添加LI元素的方法
Mar 21 Javascript
原生JS实现仿淘宝网左侧商品分类菜单效果代码
Sep 10 Javascript
jQuery插件FusionCharts实现的2D柱状图效果示例【附demo源码下载】
Mar 06 Javascript
JS实现经典的中国地区三级联动下拉菜单功能实例【测试可用】
Jun 06 Javascript
关于预加载InstantClick的问题解决方法
Sep 12 Javascript
vue2 router 动态传参,多个参数的实例
Nov 10 Javascript
JavaScript 中定义函数用 var foo = function () {} 和 function foo()区别介绍
Mar 01 Javascript
JS实现判断移动端PC端功能
Feb 21 Javascript
node.js中的fs.fchownSync方法使用说明
Dec 16 #Javascript
node.js中的fs.fchown方法使用说明
Dec 16 #Javascript
node.js中的fs.chownSync方法使用说明
Dec 16 #Javascript
node.js中的fs.chown方法使用说明
Dec 16 #Javascript
基于jquery的手风琴图片展示效果实现方法
Dec 16 #Javascript
node.js中的fs.lchownSync方法使用说明
Dec 16 #Javascript
node.js中的fs.lchown方法使用说明
Dec 16 #Javascript
You might like
利用递归把多维数组转为一维数组的函数
2006/10/09 PHP
PHP 截取字符串专题集合
2010/08/19 PHP
yii框架表单模型使用及以数组形式提交表单数据示例
2014/04/30 PHP
php数组键名技巧小结
2015/02/17 PHP
关于PHP文件的自动运行方法分析
2016/05/13 PHP
jQuery 判断元素上是否绑定了事件
2009/10/28 Javascript
JS 非图片动态loading效果实现代码
2010/04/09 Javascript
预加载css或javascript的js代码
2010/04/23 Javascript
javascript分页代码(当前页码居中)
2012/09/20 Javascript
在JavaScript中处理字符串之link()方法的使用
2015/06/08 Javascript
nodejs爬虫抓取数据乱码问题总结
2015/07/03 NodeJs
简单谈谈javascript中this的隐式绑定
2016/02/22 Javascript
JS操作COOKIE实现备忘记录的方法
2016/04/01 Javascript
JS实现屏蔽网页右键复制及ctrl+c复制的方法【2种方法】
2016/09/04 Javascript
jQuery包裹节点用法完整示例
2016/09/13 Javascript
js中获取 table节点各tr及td的内容简单实例
2016/10/14 Javascript
原生js实现可爱糖果数字时间特效
2016/12/30 Javascript
JavaScript异步上传图片文件的实例代码
2017/07/04 Javascript
微信小程序webview 脚手架使用详解
2019/07/22 Javascript
jQuery实现弹出层效果
2019/12/10 jQuery
JS实现百度搜索框关键字推荐
2020/02/17 Javascript
JS常用跨域方法实现原理解析
2020/12/09 Javascript
Python利用ansible分发处理任务
2015/08/04 Python
基于python中pygame模块的Linux下安装过程(详解)
2017/11/09 Python
分享一个简单的python读写文件脚本
2017/11/25 Python
python爬取基于m3u8协议的ts文件并合并
2019/04/26 Python
pyinstaller打包程序exe踩过的坑
2019/11/19 Python
Django 解决model 反向引用中的related_name问题
2020/05/19 Python
Django数据模型中on_delete使用详解
2020/11/30 Python
什么是makefile? 如何编写makefile?
2012/08/08 面试题
最新大学职业规划书范文
2013/12/30 职场文书
植物生产学专业求职信
2014/08/08 职场文书
师范生见习报告范文
2014/11/03 职场文书
大学生自荐信怎么写
2015/03/26 职场文书
2015年青年教师工作总结
2015/05/25 职场文书
小学语文教学随笔
2015/08/14 职场文书