使用命令行API更轻易得调试Web应用

原文链接:http://developer.telerik.com/content-types/tutorials/easier-web-application-debugging-command-line-api/

图片 文章参考截图

很多年以前,调试一段JavaScript代码几乎全部依赖于console.log()来调用正在研究中的一个或多个函数。有时你已经意识到,问题不是在这些功能而是在一个由他们调用的函数中,从而更加使得console.log()的调用将被添加到代码中。这通常也会伴随着相当多的脏话(吐槽?抱怨?)。

这种方法的问题是它降低了研究的效率。如果你正在执行一个严重的调试会话来找到一个bug的根源,那么在工作中调用console.log()并不是正确的工具。另外,有时遗留在代码中的脏话可能会导致一些尴尬的情况。

如今,大多数开发者都很好的意识到在所有主流浏览器的集成开发工具所提供的强大功能。它们提供检查DOM元素的能力,动态的添加和删除class,改变一个属性的值,在一个或多个元素上添加事件监听器以及更多。除了这些功能,开发者工具还支持命令行API。

在这篇文章中,我将向你们介绍命令行API所提供的的主要特点以及解释说明它们的使用案例。

介绍命令行API

命令行API为执行公共的任务提供了一组功能如选择和检查DOM元素,监控事件监听器,以及停止和启动系统分析器(直译:事件探查器)。它们其中的一部分也能够通过开发者工具所提供的用户界面被启用,但是如果你使用用户界面你就不得不在开发者工具选项卡之间来回移动。通过使用命令行API,你可以无需离开“Console”这个选项卡而去执行所有的操作。

让我们开始讨论这个我认为是最常见的任务:使用DOM选择一个或多个元素。

选择DOM元素

如果你喜欢jQuery,就像我一样,喜欢这个库的简单和简洁,因为它可以使用DOM来选择元素。例如,如果你想选择有一个class名为green的第一个span元素,你可以这样写:

1
$('span.green')[0]

在现代的浏览器中你可以用一个稍微冗长的语句实现相同的效果:

1
document.querySelector('span.green')

命令行API提供了一个叫作$的方法,它是document.querySelector的一个别名,用jQuery的简洁语法来执行相同的任务。因此,不像jQuery,你甚至不需要追加[0]去访问第一个元素,如下所示:

1
$('span.green')

为$而战

美元符号的选择已经给一些开发者造成了困惑。实际上,如果你正在开发的页面上使用开发者工具为美元符号定义的值(就像jQuery那样),命令行API的$别名是不可用的。以类似的方式,如果网页使用任何命令行API暴露提供的别名,那么相关的功能也将不可用。这也就意味着如果你在控制台使用$符,它可能不会立即显示$的值(document.querySelector定义的别名为jQuery,或者网页的作者定义的其他的别名)。

在一些浏览器中,如Opera和Chrome,通过查看在控制台打印的值来避免困惑是有可能的。所以,在控制台写$并且按下ENTER键。如果你看到下面的输出:

1
function $(selector, [startNode]) { [Command Line API] }

你将会知道你正在处理的命令行API的别名。不幸的是,IE11及以下版本不会给出这么nice的输出结果,因此很难理解你正在做(处理解决)什么。

选择多个元素

以同样的方式,你可以从DOM中使用$别名选择一个单一的元素,命令行API为document.queryselectorall定义了一个别名命名为$$。它可以让你选择所有的匹配所提供的选择器的DOM元素。

因此,当你在控制台中,可以通过如下写法就可以选择所有页面上的段落:

1
$$('p')

选择一个或多个元素并不令人感到多么兴奋,除非你用他们做一些事情。你可能需要改变一个属性的值,删除一个class,更改内容,或者甚至在DOM树内部移动元素。为了实现这些目标,你必须在它们的上下文环境中检查这些元素。让我们来了解如何去做。

检查DOM元素

一旦你已经选择了一个元素,你可能想要去检查它。命令行API提供了一个叫作inspect的方法,它将在开发者工具的“Elements”选项中直接带你到特定的元素。比方说你想去搜索并监测页面中第一个有classgreensapn元素。达到那样的效果你可以这样写:

1
inspect($('span.green'))

一旦你已经开始通过修改一些元素来玩DOM树,你可能想要去复用它们去执行更多的变化。命令行API提供了一个快速的方法去访问到最后选中的元素,我们将在下一节分析它。

引用监测的最后一个元素

命令行API提供的$0, $1, $2, $3$4快捷键是指在“Elements”面板内监测的最后五个DOM元素。$0命令是指最近选择的元素,$1返回第二最近选择的那个等等。如果你是正在操作在“Profiles”这个面板中而不是“Elements”这个选项中的话,这些相同的命令也能够被用来指选中的最后五个JavaScript堆对象。

调试事件

如果你在客户端用JavaScript做了一些工作,那么你一定使用了事件。在这一章节中,我将概述可调试事件监听器的方法。

检索绑定到一个元素上的事件侦听器

DOM API提供了addEventListener()removeEventListener()方法来分别添加或者删除事件监听器。不幸的是,DOM API并不提供一种检索已经添加了事件监听器的方法,因此你必须自己去跟踪它们。命令行API实现了叫作getEventListeners()的这样一个方法。记住,像这个API的其他所有功能,这个方法只有在控制台是可用的。

getEventListeners()接受你想作为其唯一的参数监测DOM元素(如window或者表达式$('span.green')的结果)。返回值是一个键为绑定事件类型名称的对象,比如“click”和“keydown”,以及值为包含为每个注册的事件监听器项目的数组。这些项目在每个数组中是描述注册了监听器的对象。

前面的描述可能有点混乱,所以让我们讨论一个例子。思考下面的代码:

1
2
3
4
5
6
7
8
9
window.addEventListener('load', function() {
console.log('loaded');
});
window.addEventListener('resize', function() {
console.log('resized 1 ');
});
window.addEventListener('resize', function() {
console.log('resized 2');
});

如果你打开开发者工具“Console”选项并执行getEventListeners(window),你将得到如下结果:

图片 控制台输出结果图

监控事件监听器的执行

有时你需要知道当一个给定的事件监听器的执行和监测传入的事件对象。在这种情况下你可以使用monitorEvents()方法。它接收两个参数,第一个参数是事件绑定对象或是相关事件的对象。第二个参数是一个指定事件名称的字符串(如“click”),一个事件集合的数组,或者是如下图所示的一个映射到预定义事件集合中的普通事件类型:

图片 事件

当一个指定的事件发生在指定的对象上,事件对象被传递给函数将被记录到控制台中。

考虑到前面的例子,你可以使用monitorevents()方法如下所示:

1
2
3
4
monitorEvents(window, 'load')
monitorEvents(window, ['load', 'resize'])
monitorEvents(window, 'control')
`

请注意,monitorevents()对自定义事件不起作用。

API还有一个叫作unmonitorEvents()停止监测事件的方法。它接受一个或两个参数,他们的类型和意义和monitorEvents()方法是一样的。如果只提供第一个参数对象,该对象将被停止。所有对象的事件将被停止监测;否则,只有指定的事件将停止被监测。

检测及监控功能和方法

去了解是什么导致了项目中的bug,你往往需要去建立和移除断点去监测方法被调用以及有哪个参数。本节将教你如何直接在控制台来达到这些目标。

设置和移除断点

通过UI界面设置和移除断点会变的无趣,因为你必须在开发者工具中切换tab选项去找到你想调试的功能。幸运的是,命令行API已经用debug()方法覆盖了此功能。它只接受一个参数用来调试你想调试的函数和方法。

一些实例调用:

1
2
3
4
5
6
// 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()

让我们讨论一个例子来搞清楚这个函数的功能。我们说在你的项目中有一个叫作sum()的方法用来计算提供的参数。为了使它更灵活,该函数接受一个数字的数组或很多数字的变量。该函数可以定义如下:

1
2
3
4
5
6
7
8
9
function sum(numbers) {
if (!(numbers instanceof Array)) {
numbers = [].slice.call(arguments);
}

return numbers.reduce(function(prev, curr) {
return prev + curr;
});
}

打开”Console”选项并执行monitor(sum)方法,然后执行下面的语句:

1
2
console.log(sum(1, 2, 3));
console.log(sum([4, 5, 6]));

开发者工具应该给你如下两个消息:

1
2
function sum called with arguments: 1, 2, 3
function sum called with arguments: 4,5,6

一旦你完成了你的研究,你可以通过调用unmonitor()来停止监控功能。

结论

在这篇文章中我已经描述了命令行API最重要的功能。它提供了一些额外的功能和快捷方法用来可以提高你的调试工作。如果你对剩下的其他工具感兴趣,这里有一些有用的资源:

坚持原创技术分享,您的支持将鼓励我继续创作!