JavaScript 的调试工具在近年来有了长足发展,几乎每一款主流浏览器都配备了专门的调试工具。Google 的 Chrome 浏览器自带了 JavaScript 调试工具 developer tools(以下统称开发者工具)。这款工具在易用性、稳定性和调试效率方面并不逊于其他常用调试工具(如 FireBug),并且它增加了很多其他工具所不具备的新功能。本文着重从调试 JavaScript 代码的角度,详细介绍如何通过 Chrome 的开发者工具高效、准确地进行 JavaScript 问题定位与调试。
Google Chrome 是由 Goole 公司开发的一款网页浏览器,自 2008 年 9 月第一个测试版本发布以来,其市场占有率逐步上升,至 2014 年 5 月,Chrome 已超越 Firefox 成为全球市场占有率第二的浏览器。Chrome 的受欢迎程度与其优秀的性能与兼容性密不可分,并且越来越多的网络应用程序都添加了对 Chrome 的支持,也足以体现网络应用的开发人员对 Chrome 的认可与青睐,而其中最重要的原因之一,莫过于 Chrome 所提供的强大的开发者工具。Chrome 开发者工具包含诸多强大的功能模块,适应于多个不同场合的需要。本文先简单介绍 Chrome 开发者工具的各个模块及其基本功能,再着重针对网页脚本调试,阐述如何巧妙运用 Chrome 开发者工具定位与调试问题。(本文所选的 Chrome 开发者工具为 Chrome V35 版本中内置,较之前版本可能略有不同,请留意)
虽然对于 Chrome 开发者工具的介绍,Google 官方以及互联网中都有众多文章进行阐述,但为了有助于读者更好地理解本文后面对如何巧妙运用开发者工具定位及调试脚本的阐述,在此对开发者工具中的各个模块做一个概要性的介绍。如果对其中某些模块特别有兴趣,请参考文末的链接,从中进行深入了解。
Chrome V35 版本中的开发者工具分为 8 个大模块,每个模块及其主要功能为:
后文会在阐述过程中,会提及使用 Element 标签页探测页面元素并查看该元素的 HTML 内容,也会使用 Source 标签页与 Console 标签页调试脚本及查看调试信息,并不会详细介绍他们的基本功能,请在阅读时提前了解以上相关标签页的基本功能。
回页首
目前很多的网页应用程序都会使用各种诸如 JavaScript 之类的脚本语言,来增强事件处理、页面展现或是样式控制等方面的功能。很多网站或网络应用系统都已做成单页面模式,该页面只负责加载相关的脚本与样式,这些脚本与样式来负责动态生成更多的子页面或对话框。因此,该类网页应用程序的脚本数量会非常大,从而使开发人员在如此之多的脚本中定位某个问题变得困难起来,但也并非毫无技巧。
单页面的网络应用程序一般会引入复杂的 JavaScript 框架,如 JQuery, Dojo 或 ExtJS 等。这些框架都支持声明自定义的网页小组件,如 Dojo 中的 widget。一般而言,每一个 widget 会被单独写在一个 JS 文件中。因此,在定义该组件时,可以将储存它的 JS 文件名做为其 id 成员属性的一部分(例如前缀),并在描述该组件的 HTML 模板中,将 id 的值加入到 HTML 标签的属性中。当应用程序在 Chrome 浏览器中运行时,在使用 Chrome 开发者工具的"元素"模块中的元素探测功能查找 HTML 时,可以很直观地看见每一个 div 对应的 JS 文件。因此,当某一个 div 出现问题时,对其 HTML 进行探测后,便可根据其中的 id 定位到相应的脚本文件,从而使问题调试的范围大大缩小。以下通过实际项目中的例子加以说明。
dojo.declare("exc.fe.bijits.FeLogon.FeLogonLogonPanel",[exc.kc._Bijit, dojox.dtl._Templated,], { templatePath: dojo.moduleUrl('exc.fe.bijits.FeLogon', "FeLogonLogonPanel.html"), select : null, SESSION_ID_OFFSET : 0, sessionid : null, launchType: "Standard Login", langcnt: 0, currentLang:null, ……//省略之后不相关的方法和属性 …… });
在清单 1 中给出的是使用 Dojo 创建自定义 widget 并将该 widget id 引入其模板 HTML 中的方式。自定义的 widget 在继承了 dojox.dtl._Templated 之后,Dojo 有内部机制可将该 widget 声明的名称作为 id 自动加到其 HTML 模板中。因此开发人员只要保证该 widget 声明的名称与其所储存的文件名对应即可。清单 1 中的 id 与储存该脚本的文件名均为"exc.fe.bijits.FeLogon.FeLogonLog-
-onPanel"。
在此前提下,打开浏览器运行网页加载该 widget 后,使用 Chrome 开发者工具的网页元素探测功能找到该 widget,便可看见其 id,即相应的脚本文件,如图 1 所示。如若该 widget 中的行为出现异常,例如 user id 不能进行校验,便可打开其相关的脚本文件进行调试。
在 Chrome 开发者工具中,可以开户运行时错误自动暂停这一功能(如图 2 所示),从而使开发者工具能在发现运行时脚本异常时,在异常脚本处暂停运行,跳转至调试页面,供开发人员进一步查找该运行时异常产生的原因。
自动暂停按钮的下方有一个选项,Pause On Caught Exceptions,如果勾选上,则即使所发生运行时异常的代码在 try/catch 范围内,Chrome 开发者工具也能够在错误代码处停住。
在进行脚本开发过程中,在重要的方法中添加必要的调试日志输出语句,可以方便开发人员进行问题定位与调试。清单 2 中的 JavaScript 脚本方法中,在其开始和结束处添加了 debug 级别的日志输出,从而使该方法在被执行时,可在 Console 标签页找到相关日志,并且能通过点击该日志的末端文件链接直接跳转到 Source 标签页的脚本源文件中,极大方便了相关代码的定位,如图 3 所示。
_containerSelect : function( /*ContentPane*/ cp ) { var F = this.declaredClass + "._containerSelect(): "; console.debug(F,"Starting: ", cp);//当方法被执行时,在控制台输出相关日志 dojo.forEach( this.children, function(child) { if ( cp.id === child.targetId ) { this.showChild( child.id ); //-- Save requested module this._history.push( child.id ); //kak if(this.globalArgs._showModuleTopic) dojo.publish(this.globalArgs._showModuleTopic, [ child.id,"open" ]); } }, this); console.debug(F,"End");//当方法执行结束后,在控制台输出相关日志 },
回页首
上文介绍了 3 种定位相关脚本的方法,在定位脚本之后,通常会对脚本中的部分代码进行调试,本章主要详细讲解高效快捷地利用 Chrome 开发者工具进行 JavaScript 脚本调试的几种技巧与心得。
与 Java 调试类似,Chrome 开发者工具提供了断点设置、删除与断点存储等基本功能。同时,开发者工具也提供了设置条件断点的功能,使开发者可以控制该断点只有在满足某一条件时才会被触发。
条件断点的设置如图 4 所示,在所需要设置断点的行最前端的行号处点击右键,选择添加条件断点后,会弹出一个对话框用于输入具体的条件。合理运用好条件断点能够提高调试的效率与准确性,使开发人员能更专注于在期望的场景下进行调试。
这是 Chrome 开发者工具提供的一种非常实用的功能,即使开发人员可直接对开发者工具的 Source 标签页中的代码进行修改,并将其保存,使浏览器在下次执行该段脚本时,直接加载最新修改的版本。目前的 Firebug 及 IE 自带的开发者工具都不支持对脚本的直接修改,导致在 Firefox 或 IE 中调试脚本时,如果需要对代码进行修改,需要先去修改脚本源文件,再同步至应用服务器,再清理浏览器缓存,最终再次打开应用程序时,才会看到代码修改后的效果。可见 Chrome 开发者工具提供的这一功能,大大提供了开发者调试脚本的效果。
需要注意的是,由于这种修改是保存在浏览器缓存中,因此它不会影响到脚本的源文件。当开发人员决定采用修改之后的脚本时,需要将其复制到脚本的源文件中。
当断点被触发进入到调试模式时,我们可以将当前任意存在的变量或方法输入到控制台中,按下回车后,控制台便会返回相关的结果。该功能可使开发人员方便了解程序运行至断点处时各个所需要变量或方法的返回值。
需要注意的是,当在控制台中输入的方法名字不带括号时,控制台输出的是该方法所包含的代码信息,而并不是运行结果。
在网页开发过程中,经常需要在脚本中控制不同条件下页面的样式展示,例如要求某一个按钮的颜色在用户停留十秒钟之后由白色变成灰色。此时我们便需要在脚本中通过具体的数值指定这个"灰色"该如何表示,一般情况下我们需要查找相关资料或使用其他工具才能得到期望的"灰色"所对应的 RGB 数值或十六进制数值。然而在 Chrome 开发者工具的 Element 标签页中,其实已经提供了包括该功能在内的一系列对样式进行实时修改的功能,并且在修改之后能够立即从页面中看到变化。
图 4 给出的是 Element 标签页的右半部分,当要对某个样式类中的颜色进行修改时,它提供出一个非常直观的图谱供选择,并在下方将其十六进制代码显示出来。开发人员可直接在此进行颜色选择,确定颜色后,在 JavaScript 代码中引用其十六进制数值即可。
回页首
Chrome 开发者工具的功能丰富而强大,本文着眼于对 JavaScript 的定位与调试,介绍了其中的技巧与心得。相对于 Firebug 与 IE 开发者工具而言,Chrome 所提供的一些独特功能如对脚本源码的直接修改,极大方便了开发者对脚本的开发与调试。随着 Chrome 新版本的推出,相信其开发者工具的功能也会日益增强,我们可以通过阅读其官方更新说明,了解到新功能,借助 Chrome 开发者工具的支持,提高网页应用程序开发与调试的效率。