Casper Beyer Self-proclaimed developer advocate, hate slow software. Grew up with C, work with JavaScript and a fan of Go.

Keeping it simple with the JavaScript console

3 min read 1007

I’ll admit it, I don’t always use a debugger to figure out what’s going wrong in my program. If my mouse clicks start printing documents down the hall, then it’s time to break out the most powerful of all debugging tools: the console.

The reason is quite simple. When a program is interactive, involving a break-step debugger becomes tedious and interrupts the flow. In times like these, it’s easier to just jump into a few key places in the code and trace the program’s state to figure out where the program is taking a wrong turn.

Displaying objects

The console.log method, and its friends console.warn and console.error, lets you dump objects in the console. The only difference between these functions is their “type” classification, which looks slightly different and can be filtered when viewing the console output.

For example,

console.log(document.head, document.body);

Will output something like the following, depending on the browser (this is from Firefox, but the general functionality is the same across browsers):

In most browser implementations, this will display an interactive list of the specified JavaScript objects’ properties, with an expandable tree view of the objects.

There’s also console.dir, which lets you do the same for a singular object, but there’s a slight difference in the representation.

For example,


Will output the following:

The only notable difference between the two is that, when printing an object, console.log gives special treatment to HTML elements, while console.dir displays everything as plain objects.

We made a custom demo for .
No really. Click here to check it out.

Note: There’s also console.exception, but this is just an alias for console.error.

Writing formatted strings

The other form console.log and friends take is a printf-like formatted string, followed by any number of substitutions. The format isn’t as rich as printf, but it does support some of the common variants like strings with %s, integers with %d or %i, and objects %o and %O.

For example,

for (let i = 0; i < 10; i++) {
    "%s I've been called %d times, this is the document body %o",
    "Hello", i, document.body

Will result in the following being displayed, with the objects interactive as if they were used in the other variant of console.log:

There is one more substitution you can use — actually, it’s more like an escape sequence — that lets you style how the text appears in the console with CSS. That’s the %c substitution.

For example,

  "%c The quick %c brown %c fox jumps over the %c lazy dog",
  "font-size: 34px;",
  "font-size: 24px; color: brown;",
  "color: orange;",
  "color: black; font-weight: bold;"

Will be rendered as the following:

Displaying object tables

If you have a lot of data you want to look at, like a map or an array of objects, then console.table does a great job of rendering that as tabular data.

For example,

var animals = [
  { kind: 'Horse', name: 'Henry', age: 43 },
  { kind: 'Dog', name: 'Spot', age: 13 },
  { kind: 'Cat', name: ' Mittens', age: 18 },

Will be rendered like the following table:

Let’s say you only want to display a few key columns. You can avoid the step of mapping them into new objects by passing an array containing the desired column names as the second parameter when calling console.table.

For example,

console.table(animals, ['kind', 'name']);

Will render a table like this:

Tracing function calls

The console.trace method lets you dump a stack trace in the console — in other words, the path the runtime took to call that function — which is useful in tracking down the function responsible for passing bad data.

For example,

function foo() {
  function bar() {

Will output a stack trace like this:

Counting function calls

Sometimes you want to keep track of how often a block of code is called; console.count does just that. Simply provide the string it’s supposed to track, and every time it’s called, it does the counting. This is particularly useful when dealing with user input and events.

For example,

window.addEventListener('click', function(event) {

Will result in something like the following output:

To reset a counter, you just need to call console.countReset with the label, and it will reset back to zero.

Grouping information

Finally, there’s the, which visually groups information together in a collapsible list, increasing the indentation by one per level.

For example,'First group');
console.log('First message');'A group inside the first group');
console.log('A message inside the group inside the first group'); console.log('Another message inside the group inside the first group');
console.log('Second message'); console.groupEnd();

Will result in the following output:

Inspecting state

In addition to the console object, which is supported across browsers and even in Node.js, there are some functions and variables available in the browser’s developer console. Do take note, however, that these are vendor-specific, and the subset supported here varies between browsers.

For example, the $_ variable holds the most recent expression that was evaluated in the console context:

And $0 through $4 holds the most recent element that was inspected with inspect element:

Again, these are browser-specific, unlike the console object. Google Chrome has many more utility functions, which are documented here. Again, though, don’t expect them to work in other browsers.


Printing to the console is a great way to visualize things. If something simple helps solve a complex problem, why make it harder for yourself with a complex solution?

Having the flow and state visualized can really be a lifesaver, so don’t be afraid to use it. Just because something is simple doesn’t mean it’s for beginners only. I’ve been logging to the console for a decade, and I plan to do it for another one.

PS To any of my old colleagues reading this: I’m sorry for using up all your printer ink.

You come here a lot! We hope you enjoy the LogRocket blog. Could you fill out a survey about what you want us to write about?

    Which of these topics are you most interested in?
    ReactVueAngularNew frameworks
    Do you spend a lot of time reproducing errors in your apps?
    Which, if any, do you think would help you reproduce errors more effectively?
    A solution to see exactly what a user did to trigger an errorProactive monitoring which automatically surfaces issuesHaving a support team triage issues more efficiently
    Thanks! Interested to hear how LogRocket can improve your bug fixing processes? Leave your email:

    : Debug JavaScript errors easier by understanding the context

    Debugging code is always a tedious task. But the more you understand your errors the easier it is to fix them.

    LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to find out exactly what the user did that led to an error.

    LogRocket records console logs, page load times, stacktraces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!

    Casper Beyer Self-proclaimed developer advocate, hate slow software. Grew up with C, work with JavaScript and a fan of Go.

    Leave a Reply