控制台API调试方法
利用控制台API更方便的调试Web应用(chrome开发文档)
许多年前,调试JavaScript代码无非就是在要调试的函数内部插入几句console.log()
而已。有时你会发现问题的根源并不在于你正在查看的函数,而是出现在这些函数调用的其它函数内部。结果就是更多的console.log()
被插入到代码中。整个过程通常还伴随着不时的吐槽。
这种调试问题的缺点在于效率低下。如果你需要调查一个严重bu*生的根本原因,console.log()
显然难当此大任。有时这些吐槽会被留在代码里,并在日后造成尴尬。
时至今日,主流浏览器中集成的功能强大的开发者工具已经为广大开发者所熟知。这些开发者工具提供了诸如审查DOM元素,添加或删除样式类,修改属性值,为一个或多个元素绑定事件等许多功能。除此之外,开发者工具还支持控制台API。
在本文中,我会向你介绍控制台API提供的主要功能并逐一介绍如何使用它们。
控制台API简介
控制台API提供了一系列诸如选择并审查DOM元素,监控事件监听器,停止或启动性能分析器等常见任务的入口。这里提到的一些任务也可以通过开发者工具的UI界面来访问,但那样的话你就不得不在开发者工具的不同标签页之间来回切换。通过使用控制台API,你就可以在不离开“Console”标签的前提下使用所有这些功能。
让我们从最常见的操作开始介绍:选择一个或多个DOM元素。
选择DOM元素
如果你像我一样喜爱jQuery,你一定很喜欢它那简洁实用的DOM选择功能。例如,你想选中第一个带有green
类的span
元素,你可以这么写:
$('span.green')[0]
在现代浏览器中还可以用以下稍显冗长的语句实现相同的功能:
document.querySelector('span.green')
控制台API提供了一个名为$
的document.querySelector
的别名来实现相同的功能。与使用jQuery时不同,你甚至都不需要输入[0]
来访问第一个元素:
$('span.green')
关于$的斗争
选择$这个命名已经给一些开发人员造成困扰。事实上,如果当前你正在使用开发者工具的页面内部已经定义了一个名为$的变量(像jQuery一样),那么开发者工具中的$变量就不可用了。类似的,如果页面中使用了和开发者工具中某个功能相同的变量命名,那么将无法在开发者工具中访问该功能。这意味着如果你在控制台中使用了$
,你并不能很容易的分辨这个$
来自哪里(来自jQuery,还是document.querySelector
的别名,亦或是页面的开发人员定义的其它内容)。
在某些浏览器例如Opear和Chrome中,你可以通过查看输出在控制台上的内容来判断。只需要在控制台中输入$
,然后按回车键。如果你看到了:
function $(selector, [startNode]) { [Command Line API] }
那么你就可以断定你使用的是控制台API提供的别名。不幸的是,IE11以及更早的IE版本并不会输出这么简单明了的信息,因此你也就不能很容易的判断了。
选择多个元素
和通过$
来选择一个元素一样,控制台API还定义了一个名为$$
的document.querySelectorAll
的别名用来选择所有满足条件的DOM元素。
你可以通过以下语句选择页面中所有的段落元素:
$$('p')
如果只是单纯的选中一个或多个元素而不对它们进行操作并没有多大意义。通常你可能需要修改元素的某个属性,删除一个样式类,修改元素内容,甚至是在DOM树中移动元素的位置。要实现这些操作,你需要在这些元素的上下文中查看它们。现在让我们看看如何实现这一目标。
审查DOM元素
一旦你选中了一个元素,你往往需要查看它的详细信息。控制台API提供了一个名为inspect
的函数,它可以将你直接带到给定DOM元素在开发者工具中“Elements”标签下的对应位置。
假设你想查找并查看第一个带有green
类的span
元素的详细信息。那么你可以执行:
inspect($('span.green'))
当时开始修改DOM树中的元素后,你可能会想访问之前选中的某个元素来执行某些操作。控制台API提供了一种访问你最后一次使用过的元素的快捷方式。我们会在下一小节中探讨。
引用最近访问过的元素
控制台API提供了$0
, $1
, $2
, $3
和 $4
这几个变量用来快速访问在“Elements”标签下最近选中的5个DOM元素。$0
代表了最近一次选中的元素,$1
代表次最近一次选中的元素,以此类推。如果你是在“Profiles”面板下访问这5个变量,那么它们分别代表了你最近选中的5个JavaScript堆对象。
调试事件
如果你在浏览器端做过JavaScript开发,那么你对事件一定不陌生。在本节中我们将讨论一些可以帮助我们调试事件监听器的方法。
获取绑定在某个元素上的事件监听器
DOM API提供了addEventListener()
和removeEventListener()
来添加或删除事件监听器。不幸的是,DOM
API没有提供获取已经添加过的事件监听器的途径,因此你不得不人工记录这些信息。控制台API提供了一个名为getEventListeners()
的方法来实现这种功能。需要注意的是,和其它控制台API一样,这个函数只可以在控制台中使用。
getEventListeners()
接受一个DOM元素作为参数(比如window
或是$('span.green')
的返回值)。它执行后的返回值是一个对象,该对象的属性名是绑定了事件监听器的事件名(例如“click”或是“keydown”),对应的属性值则是包含了该事件下所有事件监听器的数组。数组中的每一项都描述了对应事件类型**册的一个事件监听器。
以上的描述可能听起来有些模糊,让我们看一个示例。假设你执行了以下代码:
window.addEventListener('load', function() {
console.log('loaded');
});
window.addEventListener('resize', function() {
console.log('resized 1 ');
});
window.addEventListener('resize', function() {
console.log('resized 2');
});
然后你在开发者工具中打开控制台,执行getEventListeners(window)
,你就会看到以下输出:
监控事件监听器的执行
有时你会需要了解某个事件监听器何时被执行了以及相关事件对象的详细信息。这时你可以使用monitorEvents()
方法。它接受2个参数,第一个参数指定了要监听的DOM元素,第二个参数指定了要监听的事件类型(例如“click”)或是事件类型的数组,亦或是以下列出的某个预定义好的通用事件类型的别名。
当被监听的DOM对象上某个特定事件被触发时,该事件的事件对象就会被输出到控制台。
参考之前的示例,你可以像下边这样使用monitorEvents()
方法:
monitorEvents(window, 'load')
monitorEvents(window, ['load', 'resize'])
monitorEvents(window, 'control')
需要注意的是monitorEvents()
方法不支持自定义事件。
控制台API还提供了一个名为unmonitorEvents()
的方法用来停止监听事件活动。它接受和monitorEvents()
一样的参数。如果只提供了第一个参数,则该DOM元素上对所有事件监听器的监控都会停止。
监控函数或方法
为了了解产生bug的原因,你经常需要设置或取消断点,监测函数何时被执行以及执行时传入的参数。本节将介绍如何在控制台中实现这些操作。
设置或取消断点
通过UI界面设置断点通常会比较繁琐,因为你不得不在多个标签间切换以找到你要调试的函数。幸运的是,控制台API为你提供了debug()
方法。它接受的参数只有一个,就是你要调试的函数或方法。
以下是一些使用场景:
// Set a breakpoint at the beginning of the sumNumbers function
debug(sumNumbers)
// Set a breakpoint at the beginning of the autoInit
// method of the Sticky object
debug(Sticky.autoInit)
一旦你对某个函数执行了debug()
方法后,每次该函数执行时都会自动进入断点。当你调查完毕后,你可以通过undebug()
方法来移除断点。
监控函数的调用参数
有时断点并不是最适合的工具。例如在某些场景下一个函数在短时间内会被多次调用,你关心的只是该函数何时被调用已经调用时传入的参数。在这种情况下,你可以使用monitor()
方法。
为了更清楚的解释monitor()
的功能,让我们看一个实际的例子。假设我们的项目中有一个名为sum()
的函数用来计算传入参数的总和。为了增加其灵活性,它可以接受一个数组作为参数,也可以传入任意数量的数字作为参数。以下是该函数的定义:
function sum(numbers) {
if (!(numbers instanceof Array)) {
numbers = [].slice.call(arguments);
}
return numbers.reduce(function(prev, curr) {
return prev + curr;
});
}
打开控制台后执行monitor(sum)
,然后执行以下2行代码:
console.log(sum(1, 2, 3));
console.log(sum([4, 5, 6]));
这时你应该会在控制台上看到以下2行信息打印出来:
function sum called with arguments: 1, 2, 3
function sum called with arguments: 4,5,6
调查结束后,你可以通过针对该方法执行unmonitor()
来停止监控。
小结
本文中我介绍了控制台API中最重要的几个特性。这些额外的功能和快捷访问的方式可以帮助你改善调试流程。如果你对控制台API中的其它功能感兴趣,请参考以下链接:
-
Firebug’s page on the Command Line API(https://getfirebug.com/wiki/index.php/Command_Line_API)
-
Google Chrome’s page on the Command Line API(https://developers.google.com/web/tools/chrome-devtools/debug/command-line/command-line-reference)
-
Safari’s page on the Command Line API(https://developer.apple.com/library/mac/documentation/AppleApplications/Conceptual/Safari_Developer_Guide/Console/Console.html)
上一篇: Matlab —— 基础绘图