Venkman(JavaScript Debugger )
1、安装
Venkman为Mozilla浏览器(包括Firefox)开发的调试器*工具。下载地址:http://www.hacksrus.com/~ginda/venkman/ ,用Firefox打开下载下来的文件,它会自动的。安装后会发现在Tools—>Web Development菜单下多了一个新的条目。当然也可以通过Firefox的插件直接安装,请看下面:
在Firefox上如下安装:打开Firefox浏览器,工具—>附加组件 ,显示如下窗口:
注:先请下载最新firefox,链接为http://ftp.mozilla.org/pub/mozilla.org/mozilla.org/firefox/nightly/latest-mozilla-central-l10n/ ,我下载的是firefox-3.7a1pre.zh-CN.win32 ,以前用的Firefox为3.5.3版本,装JavaScript Debugger 0.9.87.4 时老时说版本不兼容,所以就换成3.7版本的了,装后就可以安装0.9.87.4版本的JavaScript Debugger了。
在附加组件窗口中点击 浏览全部附加组件 链接,显示如下窗口:
输入Venkman,并选择范围 网页开发,按提示安装即可。
我安装的fireFox与JavaScript Debugger版本如下:
2、运行
要运行Venkman,可点击Tools—>Web Development—>JavaScript Debugger来手工打开窗口,它会将所有包含JavaScript的文件自动载入到调试器窗口。
当然也可在代码中使用debugger命令,一旦遇到debugger 命令,调试器会自动开启并在这一行代码上停止执行。与IE不同的是,Mozilla不会询问你是否希望调试某个错误。
3、窗口
Venkman窗口,如下图所示,要比Microsoft Script Debugger复杂得比,当然也要强大得的多。
窗口由一些包含关于正在检查的脚本的不同信息的小窗口(也叫视图)组成。每个视图都由一些共同的组件组成,如下:
在Venkman中有八个视图可用:
- Loaded Script——显示包含JavaScript的文件,HTML或者是外部JavaScript文件,然后展开每个文件会出现其中包含的函数,显示函数名和函数开始的行号。
- Open Windows——显示Mozilla打开的所有浏览器窗口(和标签页),在每个窗口下是已经载入的HTML文件,再下面是JavaScript文件的列表,可以通过邮件点击给定文件然后选择Set As Evalution Object来在不同的窗口之间切换调试器的焦点。
- Local Variables——遇到断点时,该视图中便会出现在执行的代码的范围内可用的所有变量的列表。如果变量包含的是对象,也可能展开变量名来查看对象所有的特性。在断点处停止执行后,如果要更改变量的值,只需双击变量名,然后输入新的值。
- Watches——显示调试器会话的监视器的列表,监视器的工作就是监视变量值的变化。一旦变量的值发生变化,Watches视图中就会自动更新。
- Breakpoints——显示调试器会话中已经注册的断点的列表。
- Call Stack——遇到断点时,该视图会显示调用堆栈(到断点处的函数调用的序列)。
- Source Code——显示任何包含JavaScript的文件的源代码。
- Interactive session——一个传统风格的调试器的命令行界面。在这个视图中,利用文本命令几乎可以控制调试器任何方面。
interactive session(交互式会话)
窗口的右**意到有一个名字叫“interactive session”的面板,当你启动venkman时它就开始显示信息。带有过程处理的文本以venkman命令或其他的形式输入时以JS来执行。我们来试试在下面的输入框中写进“1+1”,接着回车。输出箭头右边显示结果“2”。
让我们再进一步尝试,输入“b=65”[可在交互式会话中输入任何类型的代码,包括变量声明]。
因为这是JS,你不仅可以声明变量,还可以使用基础MATH,调用JS中的对象,比如:String类。试着输入:String.fromCharCode(b) + "B"
结果是AB。
其他事项
注:如果视图位置弄乱了,可以使用如下命令恢复:
/restore-layout factory
在“视图”菜单中,你可以看到这两个选项“现在就保存默认版面”Save Default Layout Now和“退出时保存默认版面”Save Default Layout On Exit。如果你想为将来的用途而保存自己设置的某一个面板,记得按你的需求勾上。
值得注意的是,VENKMAN只提供查看的功能,并不能修改,它不是编辑器。
帮助文件
我们只需要在interactive session下的输入框中写:/help 或者是/help commandname
就可以看到浏览器中显示出的帮助文件。
4、Loaded Script面板
对于loaded Script面板中的每个文件,都可由你决定包含在其中的脚本是否该被调试。右击这个文件并选择File Options,会出现一个子菜单,如下,从中可以控制调试以及profiling。
如果不想调试文件中的任何代码,点击Don't Debug Contained Functions(默认情况下,所有的函数都会被调试)。这个菜单还可以防止调试eval()或者时段(timeout)的代码,选择 Dont Debugging Eval/Timeout。
默认情况下,Venkman会只显示已经载入到浏览器的文件;不过,它也可以载入浏览器在后台额外载入的所有文件。取消上下文菜单中的Excluded Browser Files上的钩就可以看到所有载入的文件。同样,在默认情况下,该面板只显示每个文件被载入的一个实例:取消上下文菜单中的Exclude Duplicates选项,就可以看到重复的文件实例。
在Loaded Scripts面板中的每个函数都有各自的某种程度的控制权。在函数上点击右键,会出现一个与文件上出现的上下文菜单类似的菜单。在Function Options下面,可以点击Don't Debug来强迫调试器仅忽略这个函数而非整个文件。这在 很大程度上给了开发人员更加灵活的控制权。
5、断点
Venkman 支持两种断点:硬(hard)断点和将来(future)断点。这与绝大多数调试环境都不太一样,因此我们会讨论这两种断点间的区别。
硬断点就是你经常在像Java这样的现代编程语言中使用的断点。它会指示Venkman在断点处挂起程序的执行。在收到用户的指示之前,程序不能继续执行。在 Venkman中,硬断点总是设置在函数体内。
将来断点与硬断点类似,它也指示Venkman在断点处挂起JavaScript的执行。两者的不同之处在于,将来断点总是设置在函数体外。这些代码会在浏览器加载它们之后立即执行。相反,函数体中的代码则一直到该函数响应用户的操作或事件时才会执行。
在很大程度上,大可不必在意硬断点和将来断点之间的区别。在大部分情况下,都会使用硬断点,它们应该与其他调试环境中的断点具有相同的功能。
Venkman 提供了一个列出所有当前断点的窗口。当你调试的页面在多个文件中含有多个断点的时候,这就会非常方便。所有设置了断点的文件都会显示在 Breakpoints窗格中,在每个文件下面会列出这个文件的所有断点。
在Venkman的各种设置断点的方法中,最快最简的方法就是双击包含脚本的文件,在Source code视图中显示出代码中,找到需要设置断点的那一行代码,点击行左边的空白处(注:在可以设置断点的行旁边有一个横线)。现在看到一个B,表示设置了一个硬断点;或者是一个F,表示调试器只能设置一个未来断点,如下图。未来断点是在脚本已经完全从内存中卸载时创建的,一旦下次这个脚本被载入(如刷新浏览器),这个断点就会变成硬断点。
可通过双击(不是单击)左边连的空白来创建未来断点,但在单击后,就不能强制已经设置好的未来断点变成硬断点。
第二个设置断点为或者未来断点的方法是,用命令行界面和/break命令(设置硬断点)或者/fbreak(设置未来断点)。两个命令都有两个参数:要设置断点的文件名和行号。例如:
/break ThrowExample.htm 7
对于参数文件名,不需要输入完整的路径甚至连完整的文件名都不需要。只需要在已经载入到Venkman中的文件中能唯一确定一个文件的几字符就行了:
/break Thr 7
在创建断点后,断点会被存放在Breakpoints视图中的文件名下面。并且硬断点与未来断点为是分开存放的,所以你可能会在同一个文件下看到两种不同的条目。只有硬断点可以按照函数名和行号查看,未来断点只显示其文件名和行号。
还有多种清除断点的选项。首先,可以点击左边空白处的B或者F,令其变成横线。也可以在Breakpoints视图上点击右键,显示上下文菜单,从中可以选择清除一个硬断点,一个未来断点、所有硬断点或者所有的未来断点。
最后一种方法还是使用偏偏行界面,使用/clear命令(清除硬断点)或者/fclear命令(清除未来断点)。这些命令接受与/break以及/fbreak同样的参数:文件名与行号,同样不需要输入完整的文件名,所以下面两行是一样的:
/clear ThrowExample.htm 7
/clear Thr 7
还可以用/clear-all命令来清除所有的硬断点,以及用/fclear-all来清除所有的未来断点。
注:清除硬断点时,它会自动变成未来断点,这意味着,先清除所有的硬断点,然后再清除所有的未来断点,才能真正消除所有的断点。
6、断点,第2部分
Venkman还有一个强大的特性,可以编写定制代码,并在每次执行断点时运行这些定制代码。在Breakpoints窗口中,右键点击一个断点,选择Breakpoint Properties(断点属性)菜单项,如下图:
会打开Breakpoint Properties对话框,这是一个强大的工具,允许你修改断点的行为,即定制断点的行为来满足你的需要。
在这个窗口最上面,有两个复选框:Enable Breakpoint(启用断点)和Clear Breakpoint After First Trigger(首次触发后清除断点)。Breakpoints Properties窗口的真正强大之处在于"When Triggered,Execute"(如果触发,则执行...)复选框,如:
选中"When Triggered,Execute"复选框,会置一个文本域有效,可以在这个文本域中编写JavaScript代码,每次遇到断点时都会执行此代码。向这个定制脚本传递的参数名为_cont_,表示遇到断点的次数。
在文本域下面,可以指它每次遇到断点时该采取怎样的行为。具体行为可以根据文本域中的定制代码的返回值决定。断点的行为有以下选择:
- Continue Regardless of Result(不论结果如何都继续)
- Stop Regardless of Result(不论结果如何都停止)
- Stop If Result Is True(如果结果为true则停止)
- Early Return from Caller with Result(带着结果从调用函数提前返回)
功能最强大的可能是 Stop If Result Is True 选项,选择这个选项的话,意味着只有当定制代码的返回值为 true 时断点才会暂停。
想象一下,如果能够根据给定条件暂定执行,这会很方便。考虑以下情况,假设你在迭代处理一个很大的对象列表,并对每个对象完成某种算。在开发过程,你注意到,计算时在一个特定对象处失败了。如果能独立出数据源,只处理单个的对象,或者只是一个很小的对象列表,则没有任何问题,但是,如果只有当前使用一个很大的对象列表时错误才可能现次出现,在这种情况下,倘若失败的对象则好在列表的最后。
如果使用条件断点功能,这种情况就很容易解决。如果知道某种情况会失败,可以编写一个条件语句,只有当条件满足时断点才暂停执行。
下面显示了一小段简化的JavaScript代码,这段代码只是创建一个数据,并迭代处理这个数组,对于数组中的每个串,会向该串附加另一个串。这段代码显示了如何根据你定义的一个条件来中止脚本的执行。
function testBreakpointProperties() { var list = ['one','two','three','four','five','six','seven','eight']; var item = null; for(var i = 0; i < list.length; i++){ item = list[i]; item = 'Text is:' + item; } }
对于这个例子,你可能希望只对列表中第7项暂停执行,即 seven。如果只是在循环中设置断点,那么每次遇到这行代码时都会暂停执行,而你每次都必须手工地重新开始执行,直到列表中你感兴趣的那一项。在这个例子中,这个列表不算长,但是如果列表中有数百项,只在满足特定条件时才中止执行就会很方便。
要想只对列表中第7项中止执行,首先在所需的行上设置一个断点(item = 'Text is:' + item 句子前加断点,其他是不行的,因为那时item还未初始化),然后右键点击这行上的任意位置,选择 Breakpoint Properties,打开 Breakpoint Properties 对话框。
假设有一个简单的场景:你希望只在处理列表中第7项(也就是串seven)时断点才真正暂停执行,选中 Triggered,Execute 复选框,启用条件式断点。在所提供的方法体中输入一行代码:
retrun item == 'sevent';
然后选中 Stop if Result Is True 单选钮,指示只有当处理的项是 seven 时才暂停代码的执行。这个断点只在第7次迭代时才暂停执行,也就是item变量处于串 seven 时才中止执行。
这是一个功能很强大的技术,在很多情况都很方便。除了前面的例子外,你可能希望每隔一次遇到断点时暂停执行。要实现这个功能,需要使用取模 % 操作符确定 _count_ 参数是奇数还是偶数,页且要设置 Stop if Result is True 选项。再举一使用 Continue Regardless of Result 设置的例子,比如每次遇到断点时都执行某种日志记录功能。甚至可以使用Ajax技术向服务器发送日志信息。
7、单步跟踪
与断点一样,也有多种方法可用于单步调试源代码。最简单的方法是,使用调试工具栏,如下图:
调试工具栏由五个按钮组成:Stop、Continue、Step Over、Step Into和Step Out。
Stop按钮可以停止当前活动的脚本,而不再继续执行以后的代码。如果任何代码正在执行,在Stop按钮上面会显示三个白点来表示调试器目前未运行任何代码。不管js是否在运行,都将停止,进入"waiting-for-something-to-happen"模式。
点击stop按钮,会**Venkman的另一个功能,即下一次执行任何javaScript时都会立即暂停javaScript。一旦点击stop按钮,可以相信,下一次执行任何javaScript时,Venkman就会暂停其执行。使用setTimeout或setInterval自动运行的脚本通常很难调试,因为脚本 的入口点不好确定。通过**Stop函数,Venkamn就能捕获到脚本的入口点,如果需要,可以从这里开始调试。
Continue按钮可以恢复脚本的执行,执行过程会一直继续,直到遇到另一个断点或脚本结束。
Step Over(单步跳过)功能可以使你避免进入当前函数调用的函数。那个被调用的函数可能已经被调试过了并且你知道问题不在那儿,或者你就是不想进入那个函数的代码,因为你只关心当前函数。需要记住的是,越过一个函数并不会影响这个函数的执行;它只是表示你不打算一行一行地调试该函数。
Step Into(单步进入)选项和Step Over功能正好相反。Step Into会进入一个被调用的函数,这样就可以调试这个被调用的函数了。合理使用Step Over和Step Into可以帮助你确定错误的具体位置。
Step Out(单步跳出)代表不再执行函数。用户单击Step Out按钮,将不调试函数调用,直接跳过函数调用,不再执行调用的函数,直接跳到调用的代码行。
这些动作都可以在Interactive视图中使用下命令来完成:
Stop ——/stop
Continue——/cont
Step Over——/next
Step into——/step
Step Out——/finish
代码执行停止在某一行时,则这一行会在Source Code视图中以黄颜色突出显示。另外,包含这一行代码的函数在Call Stack视图中会有一个黄颜色的箭头:
Call Stack视图中总有个_toplevel_条目来表示全局范围,这是第一个函数被调用之外。
8、局部变量表
Local Variables(局部变量)窗口允许你在脚本执行期间查看甚至修改变量值,无论遇到断点还是暂停了脚本的妊,Local Variables窗口总会显示当前作用域中的所有变量。
Local Variables窗口总是有两个顶层项:scope和this。scope 指示当前作用域中的所有变量。由于大多数JavaScript代码都写为函数,所以当前作用域通常就是函数作用域。具体来说,就是在该函数中用关键字var定义的所有变量。注,全局作用域定义(即函数之外定义)的变量从技术上讲可以在函数中访问,但是不会显示在当前这是作用域中。
Local Variables窗口中第二个顶层项是this。this指示关键字this引用的任何对象。如果遇到函数中的一个断点,而且这个函数是对象的一部分,this引用的就是当前对象实例。this一般会引用浏览器的window对象,注,全局作用域中定义的所有变量都会出现在this项下面。
Local Variables窗口使用变量名旁边的小图标来指示变量数据类型。可用的数据类型包括:boolean double integer null object string void。
Local Variables窗口不仅是功能强大的调试工具,它还是一个很不错的学习工具,利用这个窗口,你可以检查任何对象属性或JavaScript解释器可用的变量。
9、Watches
Venkman其中一个独特的功能是它可以设置变量监视器。监视器可以监视变量内容的改动,并及时在Watches视图中反映出来。
要添加监视器,可在Local Varaibles视图中选择一个变量,右键点击,并选择Add Watch Expression。也可以在Interactive视图中使用/watch-expr命令来完成同样的工作:
/watch-expr variable_name
将变量加入Watches视图后,Watches视图的行为就与Local Variables视图一样了,可以显示每个变量当可用的值以及对象的特性。
Watches List(监视列表)与Local Variables窗口几乎是一样的,它也显示运行在当前作用域中变量的相关信息。区别在于,开发人员可以决定监视列表中显示哪些变量,与此不同,Local Variables窗口会显示当前执行脚本可用的所有变量。可以把监视列表认为是缩水后的局部这是列表。
可以向监视列表增加一个变量。
注:Venkman中的监视器都与变量名相关,但不是直接对应,所以如果在不同的范围中有两个相同的变量名,会适时显示它们的值。
10、剖析
Venkman另外一个独特的功能是,对执行进行剖析的能力。如果执行剖析(profiling),Venkman就会跟踪每个函数的情况,记录它的调用次数,每次调用花费的时间。
你可以点击工具栏上的Profile按钮来开关执行剖析功能。Venkman正在剖析时,在Profile按钮上会出现一个绿色的标志:如果未出现标志,说明它不在进行剖析。当Venkman处于剖析模式时,可以运行你的脚本。在对测试满意后,可以在Profile—>Save Profile Data As中保存测试结果。这里会出现Save File对话框,用于选择保存文件的位置。
默认情况下,对话框会建议将文件保存为HTML格式,但这是错误的,应该将文件保存为纯文本。
对脚本执行数据剖析后,每个函数在文件中都会有单独的一节,如下:
<file:/c:/Chapter%2014/Examples/ThrowExample.htm>
ThrowExample.htm: 1000 - 5000 milliseconds
Function Name: addTwoNumbers (Lines 5 - 10)
Total Calls: 1 (max recurse 0)
Total Time: 4696.75 (min/max/avg 4696.75/4696.75/4696.75)
每一节都以包含函数的文件的位置开头,接下来是包含在文件中的每一个函数。每一个函数会显示以下内容:
- 出现的行号;
- 对函数调用的总次数和最大达到的递归层次(max recurse后的数字);
- 运行这个函数总共使用的时间(单位:毫秒)、单个调用最短的时间和最长的时间,以及平均每次调用的时间。
这些信息对于找出代码中的瓶颈十分有用。
遗憾的是,剖析的数据包含了浏览器和调试器自身的信息,所以需要通读文件才能找到需要的信息。
也可以指定要进行单板的函数。右键点击Locaded Script视图,并选择 File Options —> Don't Profile contained Function,就可以设置整个文件不被剖析。如果要针对某个单独的函数禁用profiling,可以在 Loaded Scripts 视图中右键点击这个函数并选择 Function Options —> Don't Profile。