Debugging JavaScript Apps with the Console Object
Tags: javascript, webdev, tutorial, beginners
Published: 2020-01-21 00:54:58

**Subscribe to my email list now at http://jauyeung.net/subscribe/**

**Follow me on Twitter at https://twitter.com/AuMayeung**

**Many more articles at https://medium.com/@hohanga**

JavaScript has great debugging tools built into it. One simple but powerful way to debug is by using the `console` object. This object has numerous methods which allow us to inspect the state of our program at any given time. The specifics of how the `console` works vary from browser to browser, but in the most popular browsers the `console` object has become standardized.

Console Methods
===============

The `console` object is a global object. It’s a property of `window` in most browsers, and can be referenced via `window.console` or simply `console`. The `console` object has the following methods:

*   `console.assert(boolStatement, message)` log a message and the stack trace to the console if the first argument is `false`.
*   `console.clear()` clears the console.
*   `console.count(label)` log the number of times this method has been called with the given label.
*   `console.countReset()` resets the value of the counter for the given label.
*   `console.debug(message)` log a message to the console with the log level ‘debug’.
*   `console.dir(obj)` list the properties of the given JavaScript object. The content will have triangles to show the content of child objects.
*   `console.dirxml(obj)` displays an HTML or XML representation of the object if possible.
*   `console.error(message)` log an error message to the console. We can use string substitution and additional arguments to format the log message.
*   `console.group()` creates a group of console messages, indented by levels. We can move out of a level with `groupEnd()`.
*   `console.groupCollapsed()` creates a group of console messages, indented by levels with the items collapsed. We can move out of a level with `groupEnd()`
*   `console.groupEnd()` exits the current inline group.
*   `console.info(message)` log informational messages. We can use string substitution and additional arguments to format the log message.
*   `console.log(message)` used for general logging of information. We can use string substitution and additional arguments to format the log message.
*   `console.table()` log and display data in a tabular format.
*   `console.time(name)` starts a timer with the name specified in the parameter. 10000 simultaneous timers can be run on a given page.
*   `console.timeEnd(name)` stop the specified timer and log the elapsed time in second since it started.
*   `console.timeLog()` logs the value of the specified timer to the console.
*   `console.trace()` logs a stack trace.
*   `console.warn(message)` log a warning message to the console. We can use string substitution and additional arguments to format the log message.

Different Levels of Logging
===========================

Logging data is the most common use for the `console` object. To do this we can use `console.log()`, `console.info()`, `console.warn()` or `console.error()` depending on the kind of information you’re logging. They’re all styled differently.

`console.error()` is styled with a red background in Chrome, `console.warn()` is styled with a yellow background in Chrome, and `console.log()` has no special background in Chrome.

We can pass in any JavaScript data into them. For example, we can write something like:

```javascript
const obj = {a: 1, b: 2, c:3};
const message = { message: 'Error occurred' };
console.log(obj);
console.info('Info logged', 123); 
console.warn('Warning logged');
console.error('Error', message);
```

We can output as many things as we want in one line since the `console.log()`, `console.info()`, `console.warn()`, or `console.error()` methods all can take more than one argument. So we can write something like:

```javascript
const obj = {  
  a: 1,  
  b: 2,  
  c: 3  
};  
const message = {  
  message: 'Error occurred'  
};  
console.log(obj, obj, message);  
console.info('Info logged', 123, obj, message);  
console.warn('Warning logged', obj, message);  
console.error('Error', obj, message);
```

And everything will be logged. We get the following logged:

```javascript
{a: 1, b: 2, c: 3} {a: 1, b: 2, c: 3} {message: "Error occurred"}
Info logged 123 {a: 1, b: 2, c: 3} {message: "Error occurred"}
Warning logged {a: 1, b: 2, c: 3} {message: "Error occurred"}
Error {a: 1, b: 2, c: 3} {message: "Error occurred"}
```

String Substitutions
====================

With string substitutions, we can format our console in a way that’s easier to read. It works by replacing placeholders in a string with the arguments that you pass into the right of the string you’ve passed in. The following placeholders can be used for string substitutions:

*   `%o` or `%O` this placeholder will be replaced with a JavaScript object. You can click on the object name to get more data about the object when you click on the object in the console.
*   `%d` or `%i` this placeholder will be replaced with an integer. We can use this placeholder to format numbers. We can write something like `%.3d` to round numbers to 3 significant digits with leading 0s.
*   `%s` this placeholder will be replaced with a string
*   `%f` this placeholder will be replaced with a floating-point value. We can use this placeholder to format numbers. We can write something like `%.3d` to round numbers to 3 significant digits with leading 0s.

```javascript
const obj = {
  a: 1,
  b: 2,
  c: 3
};
const message = {
  message: 'Error occurred'
};
console.log('Object %o', obj);
console.info('Number is %.3d', 123.456);
console.warn('Warning: number is: %.3d', 123.456);
console.error('Error - Error is %o. Error message is %s', message, message.message);
```

If we run the code above, wherever we have the `%o` placeholder and log an object, we can click the triangle to see more data. Whenever we have `%.3d` with a number, we see our number in the argument rounded to 3 significant digits. Strings stay as strings.

Styling Messages
================

Console messages can also be styled with CSS with the `%c` directive. Any text after the `%c` directive will be styled with whatever styles are specified. We pass in the string with the `%c` directive as the first argument and the string with the styles in the second argument. For example, we can write:

```javascript
console.log("This is a %cMy colorful message", "color: lightgreen; font-style: italic; background-color: black;padding: 2px");
```

The following syntax is allowed in the style string:

*   `background` and its longhand equivalents. Note that `background-image` doesn't seem to work in Firefox, although it does work in Chrome.
*   `border` and its longhand equivalents
*   `border-radius`
*   `box-decoration-break`
*   `box-shadow`
*   `clear` and `float`
*   `color`
*   `cursor`
*   `display`
*   `font` and its longhand equivalents
*   `line-height`
*   `margin`
*   `outline` and its longhand equivalents
*   `padding`
*   `text-*` properties such as `text-transform`
*   `white-space`
*   `word-spacing` and `word-break`
*   `writing-mode`

Console Grouping
================

We can group console output by using the `console.group()` to create the group and the `console.groupEnd()` method to end the group. The `console.groupCollapsed()` method is similar to the `console.group()` method but creates a collapsed group. To view the output of a collapsed group, you can click the triangle button to open the output. For example, we can create multiple console log groups with the following code:

```javascript
console.log("Outer level");
console.group("Group 1");
console.log("Message in group 1");
console.group("Group 2");
console.log("Message in group 2");
console.group("Group 3");
console.log("Message in group 3");
console.group("Group 4");
console.log("Message in group 4");
console.groupEnd();
console.groupEnd();
console.groupEnd();
console.log("Back in group 3");
console.groupEnd();
console.log("Back in group 2");
```

Find How Long Something Takes to Run
====================================

To calculate the time that some code takes to run, we can use console timer objects. We can use the `console.time()` method to start a timer with a string that you pass in as the label of the timer. Then you can call `console.timeLog()` to log the time of the timer when it’s running and the `console.timeEnd()` to end the timer. For example, we can write the following code to see the what time a loop loops through an element:

```javascript
const arr = Array.from({
  length: 5
}, (v, i) => i);
(async () => {
  console.time("loop time");
  for await (let i of arr) {
    console.log(i)
    console.timeLog("loop time");
    await new Promise((resolve, reject) => setTimeout(() => resolve(i), 1000))
  }
  console.timeEnd("loop time");
})();
```

We can have multiple timers set simultaneously, like in the following code:

```javascript
const arr = Array.from({
  length: 5
}, (v, i) => i);
const arr2 = Array.from({
  length: 10
}, (v, i) => i);
const asyncLoop1 = async () => {
  console.time("loop time");
  for await (let i of arr) {
    console.log(i)
    console.timeLog("loop time");
    await new Promise((resolve, reject) => setTimeout(() => resolve(i), 1000))
  }
  console.timeEnd("loop time");
}
const asyncLoop2 = async () => {
  console.time("loop time 2");
  for await (let i of arr2) {
    console.log(i)
    console.timeLog("loop time 2");
    await new Promise((resolve, reject) => setTimeout(() => resolve(i), 1000))
  }
  console.timeEnd("loop time 2");
}
(async () => {
  await asyncLoop1();
  await asyncLoop2();
})()
```

If the 2 timers have different names, then they’re 2 different timers. The elapsed time of each timer will be logged individually. They can run at the same time like in the following code:

```javascript
const arr = Array.from({
  length: 5
}, (v, i) => i);
const arr2 = Array.from({
  length: 10
}, (v, i) => i);

const asyncLoop1 = async () => {
  console.time("loop time");
  for await (let i of arr) {
    console.log(i)
    console.timeLog("loop time");
    await new Promise((resolve, reject) => setTimeout(() => resolve(i), 1000))
  }
  console.timeEnd("loop time");
}
const asyncLoop2 = async () => {
  console.time("loop time 2");
  for await (let i of arr2) {
    console.log(i)
    console.timeLog("loop time 2");
    await new Promise((resolve, reject) => setTimeout(() => resolve(i), 1000))
  }
  console.timeEnd("loop time 2");
}
asyncLoop1();
asyncLoop2();
```

Then we see that the 2 timers are simultaneously from the console’s log.

Log Stack Trace
===============

We can also log the stack trace of function calls with the `console.trace()` method. We just put it inside the function we want to get the stack trace from and we can get the entire chain of function calls. For example, we can write:

```javascript
const a = () => console.trace()  
const b = () => a()  
const c = () => b()  
const d = () => c()  
const e = () => d()e();
```

Log Objects and Arrays Values in Tables
=======================================

To display log data in a table when we log objects, we can use the `console.table` command. It works with both objects and arrays. For objects, it will log the properties in the row and column if the object is 2 levels deep. For example, if we have:

```javascript
const family = {  
  son: {  
    firstName: 'John',  
    lastName: 'Jones'  
  },  
  daughter: {  
    firstName: 'Jane',  
    lastName: 'Jones'  
  }  
}

console.table(family)
```

If we have a single level object, then we get the keys on the left and values on the right. For example, if we run:

```javascript
const son = {  
  firstName: 'John',  
  lastName: 'Jones'  
}

console.table(son)
```

`console.table()` also works for arrays. We can use it to log 1-D and 2-D arrays. For one dimensional arrays, we get the indexes of the array on the left side and the values on the right side. For example, if we have:

```javascript
const arr = [1, 2, 3];  
console.table(arr)
```

If we have use `console.table()` to log a two-dimensional array, we get the indexes of the top-level array on the left and the indexes of the nested array on the top of the table, with the values of each entry in the table. For example, if we have:

```javascript
const arr = [
  ['a', 1],
  ['b', 2],
  ['c', 3]
];
console.table(arr);
```

The `console.table()` method has a second argument that restricts the columns displayed by setting an array with the keys of an object that we want to display or the indexes of an array that we want to log. This only works with nested objects that are 2 levels deep. For example, we can write:

```javascript
const family = {
  son: {
    firstName: 'John',
    lastName: 'Jones'
  },
  daughter: {
    firstName: 'Jane',
    lastName: 'Jones'
  }
}
console.table(family, ['firstName'])
```

Then we only get the `firstName` column and the corresponding values displayed. This only works with the second level properties for nested objects.

As we can see, the `console` object is very useful for logging data in our JavaScript programs. We can have different levels of logging with `console.log()`, `console.info()`, `console.warn()`, and `console.error()` methods. We can display objects and arrays in a table with `console.table()`. We can see how long code takes to run with `console.time()` and associated methods, and we can group messages with `console.group()` and associated methods.