Fabien Huet

Fabien
Huet

Web ninja //
CTO on demand

Home Github About me

🍭 Working in the DevTools, you don't use the console enough

in JavaScript

As front end developers, the browser console panel and the console API should be one of our primary tools. We all use the console.log() or console.dir() methods, but too few of us master the trace, time, profile and other magic methods that the console API provides. I will assume that you work with chrome and know how to access your console. I won’t write about the other pannels (Elements, Network…) but they are, of course, mandatory to master.

An environment to get informations from your code and to execute JavaScript

A long time ago, the only way we had to debug JavaScript was to insert an alert() method in our code, run the code and see what was return (only a string). It was awful.

Today, we can do two things :

1 + 1
2

Get general informations

To debug your code, you will make the console output informations. Here are the basic things you can output :

Primitives like strings, number and objects : with log, debug, warn and info (they are not equals but quite equivalents). It includes everything that is an object in JavaScript (like functions and arrays)

console.log( 'Hello world!' );
Hello world!

console.log( {a: 1} );
Object {a: 1}

console.log( function() { return 1; } );
function () { return 1; }

XML maps of DOM nodes with log or dirxml

console.log( document.getElementsByTagName( 'body' )[0] );
<body>
    ​<h1>​Hello World !​</h1>​
</body>​

A JavaScript object representing a DOM node with dir.

console.dir( document.getElementsByTagName( 'body' )[0] );
body
    aLink: ""
    accessKey: ""
    attributes: NamedNodeMapbackground: """
    baseURI: "file://localhost/Users/ff/Desktop/index%202.html"
    bgColor: ""
    ...

Styling outputs, formatting primitives and making substitutions

It could surprise you but the developper tools panels are actually displayed in a DOM. So, styles are valid ! We can add style to the log, format and make substitutions. Try the following command :

console.log( '%cHello World', 'color: #333; background: #eee; font-size: 12px; padding: 3px 8px; font-family: Arial, sans-serif;' );

I bet you did not know you could do that :). The %c tell the console to use the next parameter as the style.

You can also substitue elements ; try the following command :

console.log( '%s World, %i, %O', 'Hello', 1337, {a: 1} );

Nice, isn’t it ? Each time you add a %something, it will try to get the next parameter and substitue it. Here’s the list of the substitutions you can make :

<li>`%f` : float</li>
<li>`%i` : integer</li>
<li>`%O` : object</li>
<li>`%s` : string</li>

Note that you can display tables (only on chrome). Try this in your console :

console.table( [ ['v1', 'v2', 'v3'], [1, 2, 3] ] );
console.table( [ {head1: 'v1', head2: 'v2', head3: 'v3'}, {head1: 1, head2: 2, head3: 3} ] );

Useful when you have complex data to log.

Quick and dirty performance check : console.time()

You remember the old way to check how long a method took to execute ? Creating a Date object, calling the method to check, and then creating a new Date, subtracting the old one and output the result. This was ugly and not precise. Today, you should use the console.time() and console.timeEnd() methods. It take a sting as parameter and give you a nanosecond precise timing.

It’s now easy to compare how long it takes to create an Arrayof 10 million elements and an Uint8Array of the same length.

console.time( 'slow' );
var array = new Array( 10000000 );
console.timeEnd( 'slow' );
slow: 42.949ms

console.time( 'quick' );
var quickArray = new Uint8Array( 10000000 );
console.timeEnd( 'quick' );
quick: 7.612ms

time() starts the timer, and timeEnd end the timer and logs the time it took. This is a powerful tool.

Log errors and get the stack trace

Two simple methods info and warn allow you to log primitives in the console. Nothing special here but a small pictogram in the beginning of the message for styling purpose. i for infos and !for warn.

console.error() and console.trace() are immensely more useful (and almost equivalent). It does not only logs the primitive target, it logs the stack trace. So you can see all the calls that happened to end up in the context where the console call is placed. Try them if you don’t use them on a daily basis.

Start advanced debugging programmatically

There are three advanced debugging tools : the step by step debugger, the profiler and the timeline. And you can start all of then from your code.

The debugger

To start the step by step debugger is as simple as insert debugger; in your code. Try the following command in your console :

( function () {
    debugger;
    var a = 1;
    a++;
} )();

It will simply open the debugger and you can access its capacities.

The timeline

To start the timeline, the timeline method of the console API is used. Your start it with a label and then stop it with timelineEnd with the label as parameter. This is useful to get a quick overview of what takes time in your code and in witch order things happen. Try that in your console :

( function () {
    console.timeline( 'timeline1' );
    var a = new Array( 100 ).join( '0' ).split( '' );
    a.forEach( function ( el, index ) { console.log( index ) } );
    console.timelineEnd( 'timeline1' );
} )();

It will output this messages :

Timeline 'timeline1' started.
Timeline '' was not started.

An then you can open your Timeline panel. This is not the most interesting timeline you will see. But a timeline a real project is always informative. You will know globally where are the bottlenecks that kill your performances.

The profiler

To start the profiler, the profile method of the console API is used. You start it with a label and then stop it without parameter. You can after go in the Profiles panel to study the result. This is useful for very advanced debugging. Try this in your console :

( function () {
    console.profile( 'profile1' );
    var a = 1;
    a++;
    console.profileEnd();
} )();

It will output the following messages :

Profile 'profile1' started.
Profile 'profile1' finished.

And then you can open the Profiles panel and see that you have now a profile1 in the CPU profiles list. It will show you precisely how your processing power is spent. To make your optimizations choice, this is what your are going to monitor.

Test your code

If you test your code (and you should), you use the assert method of your testing framework on a daily basis. The one from the console is not meant to replace any testing framework, but it’s always interesting for testing small chunks of code in development mode. Try this in your console :

console.assert( 1 < 10, 'the assertion failed' )

console.assert( 1 > 10, 'the assertion failed' )
    Assertion failed: the assertion failed
        (anonymous function)
        evaluate
        InjectedScript._evaluateOn
        InjectedScript._evaluateAndWrap
        InjectedScript.evaluateOnCallFrame
        InjectedScript.RemoteObject
        InjectedScript._wrapObject
        InjectedScript._evaluateAndWrap
        InjectedScript.evaluate

When the assertion pass, nothing happens, when it fails, it outputs the error.

Clear the console

The console.clear() will clear the console. As the command + k on mac os or ctrl + k on windows shortcuts will.