15.2.5 更强大的调试

Firebug控制台是显示消息以便我们在程序运行时知道发生了什么的一种好办法。但是,有时候,一个程序运行得如此之快,以至于很难在每一步中看清楚发生了什么。我们需要一种方法使这一过程慢下来。幸运的是,Firebug包含了一个强大的JavaScript调试器。它使我们一行一行地步进执行一个脚本,以便可以看到在程序的每一步发生了什么。

注意:你将会发现在Chrome、Opera、Safari和Internet Explorer 9中JavaScript调试器具有相似的功能。

调试是修正一个不能正确工作的程序的过程,也就是除错。要真正理解一个程序是如何发挥功能(或者不能正确发挥功能),我们需要一步一步地查看程序是如何工作的。

要使用调试器,可以把某些代码行标记为断点。断点是JavaScript停止运行程序并开始等待的一个位置。然后,可以使用Firebug中的控制来使得程序一次运行一行。通过这种方式,我们可以看到在任何特定的代码行到底发生了什么。如下是基本的过程。

15.2.5 更强大的调试 - 图1

图 15-5 Firebug控制台是在程序运行时显示诊断信息的一种好办法。只要在一组中的第一条console.log()消息的前面添加console.group(),在最后一条消息的后面添加console.groupEnd(),就可以把一系列的日志条目组织在一起。可以在www.getfirebug.com/console.html了解关于控制台函数的更多内容

1.在Firefox中打开一个页面。

我们需要按照15.2.1节的介绍来安装和打开Firebug。

2.打开Firebug。

单击Firebug图标(在Firefox工具栏右上角位置)。或者,按下F12键(仅适用于Windows操作系统)或者单击Firefox→Web Developer→Firebug→Open Firebug(在Windows中)或者单击Tools→Web Developer→Firebug→Enable Firebug(在Mac中)。

提示:如果不喜欢We b页面直接堆叠在Fi re b u g上的难看的样子,选择Fi re fox→We b Developer→Firebug→“Open Firebug in New Window”(在Windows中)或者Tools→Web Developer→Firebug→“Open Firebug in New Window”(在Mac中)

3.单击Script标签页(如图15-6所示)。

这个Script标签页列出了我们想要调试的文件的源代码。在写入一个Web页面中的脚本的情况下,我们看到了整个Web页面的源代码(包括HTML)。对于一个外部JavaScript文件来说,我们只是看到该文件中的JavaScript。

15.2.5 更强大的调试 - 图2

图 15-6 Firebug调试器允许我们设置断点(脚本停止并开始等待的行),控制脚本的执行,并且查看Watch列表中的变量。在调试器执行脚本的时候,当前行(将要运行的行)的左边有一个黄色的箭头(如圆圈所示)

4.从source菜单中选择带有我们想要调试的脚本的文件(如图15-6所示)。

把脚本放入不同的文件是很常见的:Web页面自身,或者一个或多个外部JavaScript文件。如果页面使用来自多个文件的脚本,我们需要选择包含了想要调试的脚本的文件。

5.添加断点。

要添加断点,单击该行代码的行号的左边。一个红色的符号出现,表示这是一个断点。

注意:给只包含注释的一行添加代码是没有效果的,调试器不会在该行停止。只能给包含真正的JavaScript代码的行添加断点。

6.重新载入Web页面。

因为必须在Firefox中查看Web页面,并且为此要打开Firebug并添加断点,我们想要调试的JavaScript可能已经运行了(在我们添加任何断点之前)。在这种情况下,需要重新载入页面,以便可以再次开始JavaScript。

如果在响应事件的一个函数中添加了一个断点(例如,我们想要调试当单击一个按钮或者把鼠标光标移到一个链接上的时候所运行的代码),那么,我们需要触发该事件,如单击按钮或者把鼠标光标移到链接上,或者通过其他的方式来触发,从而到达该断点并且开始调试过程。

在脚本开始运行之后,只要到达一个断点,脚本就会停止。程序及时冻结,等待执行断点后面的第1行。

7.使用Firebug的控件来步进地执行程序。

Firebug提供了4个控件(如图15-6所示),它们告诉程序在断点停止了之后该如何运行。我们可以阅读本小节中“用调试器控制脚本”部分对这些控件的介绍。

8.在Watch列表中监控程序条件(如图15-6所示)。

步进执行程序的目的是为了查看脚本内在任何特定的行发生了什么。Watch列表提供了关于程序条件的基本信息,并且允许我们添加要查看的条件变量。例如,如果想要跟踪在脚本运行时候变量score的值,我们可以在Watch列表中做到这一点。我们将在15.2.5节学习如何使用Watch列表。

9.在文本编辑器中修正脚本。

在步进脚本的过程中,很有可能找到脚本中哪里出错,例如,为什么一个特定变量值没有变化,或者为什了一个条件语句不会得到false。使用这些信息,我们可以跳转到文本编辑器中并修改脚本(在15.3节的教程中,我们将运行一个修改脚本的示例)。

10.在Firefox中测试页面,并且,如果必要的话,重复上述的步骤继续调试脚本。

用调试器控制脚本

一旦给脚本添加了断点并且重新载入页面,我们就准备好了一行一行地步进执行脚本。如果在页面载入的时候运行的脚本的某个部分添加了一个断点,脚本将会在断点停止;如果只是在一个事件(例如单击一个链接)后面紧接着的一行添加了一个断点,我们需要触发该事件,然后才能到达该断点。

当调试器在断点停止了程序,它不会运行那一行代码;它在运行该行代码之前就停下来。然后,我们可以单击调试器的4个按钮之一来控制调试器接下来做什么(如图15-6所示)。

·Play。Play按钮直接开始脚本的运行。在JavaScript解释器遇到另一个断点之前,或者直到脚本运行完成之前,脚本不会再次停止。如果有另一个断点,脚本再次停止下来并等待你单击调试器控件的4个按钮之一。

如果只是想要运行程序或者跳到下一个断点,使用Play按钮。

·Step Over。这个有用的选项运行当前的代码行,然后在脚本的下一行停止。它的名字叫做Step Over,因为如果当前代码行包含对一个函数的调用,它不会进入该函数。它跳过该函数并且在函数后的下一行代码停止。如果已经知道调用的函数其功能没有缺陷,这个选项是很好用的。例如,如果脚本调用一个jQuery函数,我们将跳过对该函数的调用,否则,会花很多时间看到一行一行的、令人惊讶的jQuery程序。大多数时候,我们将选择Step Over选项,除非在代码行中,调用的是我们自己创建的函数,那么,使用下面提到的Step Into选项来看看在函数中发生了什么。

·Step Into。Step Into使得调试器进入一个函数调用。也就是说,如果我们在包含了函数调用的一行上,调试器进入该函数并且在函数的第1行停下。当不确定主脚本中或者我们自己编写的一个函数中是否有问题,这个选项是一种可以采用的办法。

如果你确保将要调用的函数能够工作,例如,这个函数你此前已经用过很多次了,那么,可以直接跳过这个选项。当你在调试包含了一个jQuery选择器或命令的一行代码的时候,你也想要使用Step Over而不是Step Into。例如,$('#button')是选择页面上的一个元素的一种jQuery方式。然而它也是jQuery库的一个函数,因此,当你遇到一个jQuery函数的时候,如果单击了Step Into按钮,将会陷入jQuery库的复杂世界(并且,如果发生这种情况,你将会知道这种情况,因为脚本标签页会变为显示出jQuery文件的所有JavaScript代码)。

当使用调试器的时候,你会发现自己迷失在函数之中,或者迷失在jQuery这样的JavaScript库中,你可以使用下面描述的控制方法来逃脱出来。

·Step Out。Step Out按钮使得调试器走出一个函数调用。我们通常在Step Into之后使用它。当我们这么做的时候,函数正常运行,但是不会像是在常规调试模式中那样在函数中的每一行都停止。当我们单击了这个按钮,调试器返回到最初调用函数的那一行然后停下来。

查看脚本

尽管调试器顶端的按钮允许我们控制脚本如何执行,调试器的整个要点还是看看脚本中发生了什么。这就是为什么使用Watch列表(如图15-7所示)。Watch列表提供了当前指定的代码行环境中的变量和函数的一个列表。这意味着,如果在函数中放置一个断点,将会看到函数中定义的所有变量的一个列表;如果在脚本的主体中放置一个断点,将会看到在那里定义的所有变量的一个列表。我们还将看到Watch列表列出了我们所创建的所有函数。

15.2.5 更强大的调试 - 图3

图 15-7 Firebug的Watch列表在程序运行的时候显示了不同的变量的值。可以给该列表添加自己的表达式,该列表在窗口的顶部显示为灰色条纹

可以把这个Watch列表看做一种连续的console.log()命令。它在一行特定的代码运行的时候,显示出一个特定变量或表达式的值。

Watch列表提供了对程序的有价值的查看,提供了一种冻结的效果,以便我们可以找到脚本中哪里发生了一个错误。例如,如果知道一个特定的变量存储了一个数值,我们可以步进地执行脚本看看变量初次创建的时候存储到其中的是什么值,并且看到在程序运行的时候是如何修改该值的。在单击了Step Over或Step Into按钮之后,如果看到变量值改变为我们意料之外的内容,那么,可能就找到了引入错误的一行代码。