Telerik blogs
command_line_api_header

Many years ago, debugging a JavaScript code base was all about console.log() calls sprinkled in one or more functions under investigation. Sometimes you'd realize that the problem was not in those functions but in one called by them, thus even more console.log() calls would be added to the code. This usually came along with a decent amount of swearing as well.

The problem with this approach is that it slows down the investigation. If you're performing a serious debugging session to find the root of a bug, console.log() calls are not the right tool for the job. Plus, sometimes that swearing remains in the code which can cause awkward situations.

Today most developers are well aware of the powerful features provided by the integrated developer tools in all major browsers. They offer the ability to inspect the DOM, add and remove classes on the fly, change the value of an attribute, add event listeners on one or more elements, and much more. In addition to these capabilities, developer tools support the Command Line API.

In this article, I'll introduce you to the main features provided by the Command Line API and explain the use cases for each of them.

Introducing the Command Line API

The Command Line API exposes a set of features for performing common tasks such as selecting and inspecting DOM elements, monitoring event listeners, and stopping and starting the profiler. Some of them can also be enabled via the UI offered by the developer tools, but if you use the UI you have to move back and forth between the tabs of the developer tools. By using the Command Line API, you'll be able to perform all the actions without having to leave the "Console" tab.

Let's start our discussion with the task I reckon is the most common: selecting one or more elements in the DOM.

Selecting DOM Elements

If you love jQuery, as I do, you enjoy the ease and conciseness with which the library lets you select elements in the DOM. For example, if you want to select the first span having a class of green, you can write:

$('span.green')[0]

In modern browsers you can achieve the same result with a slightly more verbose statement:

document.querySelector('span.green')

The command line API exposes a function called $ that is an alias for document.querySelector to perform the same task with the conciseness of jQuery. Therefore, unlike with jQuery, you don't even have to append the [0] to access the first element as shown below:

$('span.green')

Fight for the $

The choice of the dollar sign has caused confusion to some developers. In fact, if the page you're working on using the developer tools defines a value for the dollar sign (as jQuery does), the $ alias of the Command Line API is not available. In a similar fashion, if the web page uses any of the aliases exposed by the Command Line API, the relevant feature will not be available. This means that if you're using $ in the console, it might not be immediately obvious what the value of $ is (jQuery, an alias for document.querySelector, or something else defined by the author of the web page).

In some browsers, such as Opera and Chrome, it's possible to avoid the confusion by looking at the printed value on the console. So, write $ in the console and press ENTER. If you see the following output:

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

...you'll know that you're dealing with the Command Line API alias. Unfortunately, Internet Explorer 11 and below don't give you such nice output, therefore it's harder to understand what you're dealing with.

Selecting Multiple Elements

In the same way that you can select a single element from the DOM using the $ alias, the Command Line API defines an alias for document.querySelectorAll named $$. It lets you select all the elements of the DOM that match the provided selector.

So, while you're in the console, you can select all the paragraphs of the page by writing:

$$('p')

Selecting one or more elements is not that exciting unless you do something with them. You might need to change the value of an attribute, remove a class, change the content, or even move the elements inside the DOM tree. To achieve these goals, you have to inspect the elements in their context. Let's learn how to do it.

Inspecting DOM Elements

Once you have selected an element, you might want to examine it. The Command Line API provides a function called inspect that will bring you directly to the specified element in the "Elements" tab of the developer tools.

Let's say that you want to search and inspect the first span of the page having a class of green. To do that, you can write:

inspect($('span.green'))

Once you have started playing with the DOM tree by modifying a few elements, you might want to reuse them to perform more changes. The Command Line API provides a quick way to access the last elements selected, we'll examine this in the next section.

Referencing the last Elements Inspected

The Command Line API offers the $0, $1, $2, $3 and $4 shortcuts to refer to the last five DOM elements inspected within the "Elements" panel. The $0 command refers to the most recently selected element, $1 returns the second most recently selected one, and so on. These very same commands can also be used to refer to the last five JavaScript heap objects selected if you were working in the "Profiles" panel instead of the "Elements" tab.

Debugging Events

If you've done any work with JavaScript on the client side, you've surely employed events. In this section, I'll outline the functions available to debug event listeners.

Retrieving Events Listeners Attached to an Element

The DOM API provides the addEventListener() and the removeEventListener() functions to add or remove an event listener respectively. Unfortunately, the DOM API doesn't offer a way to retrieve an added event listener, so you have to keep track of all of them by yourself. The Command Line API implements such a function called getEventListeners(). Remember that, like all the other features of this API, this function is only available in the console.

getEventListeners() accepts the DOM element that you want to inspect as its only parameter (e.g. window or the result of the expression $('span.green')). The return value is an object whose keys are the name of the event type bound, such as "click" or "keydown", and the values are arrays containing an item for each registered event listener. The items within each array are objects that describe the listener registered.

The previous description might be slightly confusing, so let's discuss an example. Consider the following code:

window.addEventListener('load', function() {
   console.log('loaded');
});
window.addEventListener('resize', function() {
   console.log('resized 1 ');
});
window.addEventListener('resize', function() {
   console.log('resized 2');
});

If you open the "Console" tab of the developer tools and execute getEventListeners(window), you'll obtain the following result:

Result of calling getEventListeners

Monitor the Execution of Event Listeners

Sometimes you need to know when a given event listener is executed and to inspect the event object passed to it. In these circumstances you can use the monitorEvents() function. It accepts two parameters. The first is the object on which the event or events of interest were bound. The second is a string specifying the name of the event (such as "click"), an array of events, or one of the generic event types mapped to a predefined set of events as shown below:

Event type Events mapped
mouse mousedown, mouseup, click, dblclick, mousemove, mouseover, mouseout, mousewheel
key keydown, keyup, keypress, textInput
touch touchstart, touchmove, touchend, touchcancel
control resize, scroll, zoom, focus, blur, select, change, submit, reset


When one of the specified events occurs on the specified object, the event object passed to the function is logged to the console.

Taking into account the previous example, you could employ the monitorEvents() function as follows:

monitorEvents(window, 'load')
monitorEvents(window, ['load', 'resize'])
monitorEvents(window, 'control')

Please note that monitorEvents() does not work for custom events.

The API also has a function to stop monitoring events that you were previously monitoring called unmonitorEvents(). It accepts one or two parameters. Their types and meanings are the same as the monitorEvents() function. If only the first parameter, the object, is provided, all the events for that object will stop being monitored; otherwise only the specified event(s) will stop being monitored.

Inspecting and Monitoring Functions and Methods

To understand what is causing a bug in a project, you often need to set up and remove breakpoints, inspecting when a function is called and with which arguments. This section will teach you how to achieve these goals straight in the console.

Setting and Removing Breakpoints

Setting and removing breakpoints via the UI can become boring because you have to change tabs within the developer tools and find the function you want to debug. Luckily, the Command Line API has you covered with the debug() function. It accepts only one parameter, which is the function or the method you want to debug.

Some examples of calls are:

// 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)

Once you call debug() on a function or method, every time it is executed, the debugger opens. Once you're done with your investigation, you can remove the breakpoint by calling undebug() on the same function or method.

Monitoring Functions and Methods

Sometimes a breakpoint is not exactly what you want. For example, in the case of a function that is called many times during a short period, you might only want to know when the function is executed and with what arguments. For such occasions, you can use monitor().

To clarify what this function does, let's discuss an example. Let's say that you have a sum() function in your project that sums the arguments provided. To make it more flexible, the function accepts an array of numbers or a variable amount of numbers. The function can be defined as follows:

function sum(numbers) {
   if (!(numbers instanceof Array)) {
      numbers = [].slice.call(arguments);
   }

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

Open the "Console" tab and execute monitor(sum) and then execute the following statements:

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

The developer tools should give you two messages like the following:

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

Once you've completed your investigation, you can stop monitoring the function by calling unmonitor() on the same function.

Conclusion

In this article I've described the most important features of the Command Line API. It offers a few additional functions and shortcuts that you can use to improve your debugging workflow. If you're interested in the remaining tools available, here are some useful resources:

Header image courtesy of Google


Telerik Blogging Ninja
About the Author

Aurelio De Rosa

Aurelio is a (full-stack) web and app developer with more than 5 years experience programming for the web using HTML5, CSS3, JavaScript and PHP. His interests also include web security, web accessibility, SEO and WordPress. He's the author of the books jQuery in Action and Instant jQuery Selectors. You can find him on GitHub here.

Comments

Comments are disabled in preview mode.