• Beyond console.log()
  • By Matt Burgess
  • The Nuggets translation Project
  • Permanent link to this article: github.com/xitu/gold-m…
  • Translator: Pomelo1213
  • Proofreader: RicardoCao-Biker, CoderMing

There are many more ways to debug JavaScript than using console.log to output values. You think I’m going to talk about debuggers? No, no, no, you got it wrong.

Telling JavaScript writers that they should use the browser’s debugger to debug their code seems like a good idea, and there’s certainly a time and place for it. But most of the time you just want to see if a particular piece of code executes or what the value of a variable is, rather than getting lost in the depths of the RxJS code base or a Promise library.

However, while console.log has its uses, most people still don’t realize that console itself has many options beyond the base log. Using these methods properly can make debugging simpler, faster, and more intuitive.

console.log()

What many people don’t know is that the classic console.log has a wealth of functional features. Although most people only use console.log(object) syntax, you can still write console.log(object, otherObject, string) and it will print everything out neatly. Sometimes it’s really convenient.

More than that, there’s another format: console.log(MSG, values). This implementation is similar to sprintf in C or PHP.

console.log('I like %s but I do not like %s.'.'Skittles'.'pus');
Copy the code

It will output exactly what you expect.

> I like Skittles but I do not like pus.
Copy the code

Common placeholders are % O (which is the character O, not 0) for an object, %s for a string, and %d for a decimal or integer.

The other thing you might not think is interesting is %c. It actually acts as a placeholder for CSS values.

console.log('I am a %cbutton'.'color: white; background-color: orange; padding: 2px 5px; border-radius: 2px');
Copy the code

The following values can be added all the time, and the absence of an “end tag” here is a bit odd indeed. But you can separate them like this.

It’s not beautiful, and it’s not particularly useful. It’s not a real button either.

Does it really work? I don’t think so.

console.dir()

In general, console.dir() functions are very similar to log(), although they look slightly different.

The drop-down arrow displays the same object information as in the console.log view. But when you look at the element nodes, the results are very interesting and very different.

let element = document.getElementById('2x-container');
Copy the code

Here is the output of the log input element:

I’ve opened up some element nodes. The DOM nodes are clearly visible, and we can jump to child DOM nodes. But console.dir(element) gives us an unexpectedly different output.

This is a more objectified way of looking at element nodes. This might be what you want in some cases, like monitoring element nodes.

console.warn()

Probably the most straightforward and obvious replacement for log(), you can use console.warn() in the same way. The only difference is that the output is yellow. Specifically, the output is a WARN level message rather than an INFO level message, so the browser handles it slightly differently. It’s useful to highlight your output in a jumble of output.

There is, however, an even greater advantage. Since the output is a WARN level and not an INFO level, you can filter out all console. logs except console.warn. This can sometimes be useful in casual applications that constantly output a bunch of useless and meaningless stuff to the browser. Blocking out distractions makes it easier to see your own output.

console.table()

Surprisingly, this is not widely known, but the console.table() method is more of a way to present tabbed data, which is cleaner than just dropping the original array of objects.

As an example, here is a list of the data.

const transactions = [{
  id: "7cb1-e041b126-f3b8",
  seller: "WAL0412",
  buyer: "WAL3023",
  price: 203450,
  time: 1539688433
},
{
  id: "1d4c-31f8f14b-1571",
  seller: "WAL0452",
  buyer: "WAL3023",
  price: 348299,
  time: 1539688433
},
{
  id: "b12c-b3adf58f-809f",
  seller: "WAL0012",
  buyer: "WAL2025",
  price: 59240,
  time: 1539688433
}];
Copy the code

If we use console.log to list the above information, we can get some unappealing output:

▶ (3) [{...}, {...}, {...}]Copy the code

This little arrow allows you to click and expand the array, but it’s not the “at a glance” that we want.

The output from console.table(data) is more helpful.

The second optional argument is the column of the list that you want to display. The default is the entire list, but we can do that as well.

> console.table(data, ["id"."price"]);
Copy the code

We get output that shows only id and price. Useful in complex objects with lots of irrelevant information. The index column is automatically generated and, as far as I know, does not disappear.

It is worth mentioning that there is an arrow in the upper right corner of the head in the rightmost column to reverse the order. Clicking on it will sort the entire column. Very convenient to find the maximum or minimum value of a column, or just to get different data presentation. This feature does nothing but show columns. But it’s always useful.

Console.table () only has the capacity to process up to 1000 rows of data, so it may not be suitable for all data sets.

console.assert()

A useful function that is often overlooked, assert() is the same as log() when the first argument is falsey. Do nothing when the first argument is true.

This is especially useful in scenarios where you need loops (or different function calls) and only one particular behavior to show. It’s essentially the same thing as this.

if (object.whatever === 'value') {
  console.log(object);
}
Copy the code

To be clear, when I said “same,” I should have said the opposite. So you need a change of scene.

So, assuming that our value above has a null or 0 in the timestamp, this will break our code date format.

console.assert(tx.timestamp, tx);
Copy the code

Skips when used with any valid object. But one triggered our logging because the timestamp was false at 0 and NULL.

Sometimes we want more complex scenarios. For example, we saw a data problem with user WAL0412 and wanted to show only transactions from them. This would be a very simple solution.

console.assert(tx.buyer === 'WAL0412', tx);
Copy the code

It looks right, but it doesn’t work. Remember, the scene must be negative, we want assertions, not filters.

console.assert(tx.buyer ! = ='WAL0412', tx);
Copy the code

That’s what we want to do. In that case, all transactions that are not customer WAL0412 are true, leaving only those that match. Or, not really.

Console.assert () doesn’t always work well. But it’s the most elegant solution in a particular situation.

console.count()

Another appropriate use is to use console as a counter.

for(let i = 0; i < 10000; i++) {
  if(i % 2) {
    console.count('odds');
  }
  if(! (i % 5)) { console.count('multiplesOfFive');
  }
  if(isPrime(i)) {
    console.count('prime'); }}Copy the code

This is not a useful piece of code and is a bit abstract. I’m not going to prove the isPrime function, just assume it works.

We’ll get a list that looks like this

odds: 1
odds: 2
prime: 1
odds: 3
multiplesOfFive: 1
prime: 2
odds: 4
prime: 3
odds: 5
multiplesOfFive: 2
...
Copy the code

And the rest. This is useful in cases where you only want to list indexes, or where you want to keep one (or more) count.

You can also use console.count() like that, with no arguments. Call with default.

There is also the correlation function console.countreset (), which you can use if you want to reset the counter.

console.trace()

This is more difficult to demonstrate in simple data. It does best when you’re trying to find calls to problematic inner classes or libraries.

For example, here you might have 12 different components calling a service, but one of them doesn’t have its dependencies configured correctly.

export default class CupcakeService {
    
  constructor(dataLib) {
    this.dataLib = dataLib;
    if(typeof dataLib ! = ='object') { console.log(dataLib); console.trace(); }}... }Copy the code

Using console.log() alone, we only know which base library was executed, not where. However, the stack trace makes it clear that the problem is dashboard.js, and we find that new CupcakeService(false) is the culprit.

console.time()

Console.time () is a function specifically designed to monitor the time overhead of an operation, and is a better way to monitor minute JavaScript times.

function slowFunction(number) {
  var functionTimerStart = new Date().getTime();
  // something slow or complex with the numbers. 
  // Factorials, or whatever.
  var functionTime = new Date().getTime() - functionTimerStart;
  console.log(`Function time: ${ functionTime }`);
}
var start = new Date().getTime();

for (i = 0; i < 100000; ++i) {
  slowFunction(i);
}

var time = new Date().getTime() - start;
console.log(`Execution time: ${ time }`);
Copy the code

This is an outdated method. I’m also referring to console.log above. Most people don’t realize that you could have used template strings and interpolation here. It will help you every now and then.

So let’s update the above code.

const slowFunction = number =>  {
  console.time('slowFunction');
  // something slow or complex with the numbers. 
  // Factorials, or whatever.
  console.timeEnd('slowFunction');
}
console.time();

for (i = 0; i < 100000; ++i) {
  slowFunction(i);
}
console.timeEnd();
Copy the code

I don’t need to do any arithmetic or set up temporary variables right now.

console.group()

Nowadays we probably output advanced and complex things on most consoles. Grouping allows you to generalize. In particular, you can use nesting. It is good at showing the structural relationships that exist in your code.

// this is the global scope
let number = 1;
console.group('OutsideLoop');
console.log(number);
console.group('Loop');
for (let i = 0; i < 5; i++) {
  number = i + number;
  console.log(number);
}
console.groupEnd();
console.log(number);
console.groupEnd();
console.log('All done now');
Copy the code

Again, this is a little hard to understand. You can see the output here.

It’s not very useful, but you can see how some of them are combined.

class MyClass {
  constructor(dataAccess) {
    console.group('Constructor');
    console.log('Constructor executed');
    console.assert(typeof dataAccess === 'object'.'Potentially incorrect dataAccess object');
    this.initializeEvents();
    console.groupEnd();
  }
  initializeEvents() {
    console.group('events');
    console.log('Initialising events'); console.groupEnd(); }}let myClass = new MyClass(false);
Copy the code

A lot of work and code may not be that useful for debugging information. But it’s still an interesting approach, and you can see how clear it makes the context of your print.

And one last thing about that is console. GroupCollapsed. It is functionally the same as console.group, but the grouping blocks are initially collapsed. It’s not well supported, but if you have a huge meaningless group and want to hide it by default, try this.

conclusion

There really isn’t too much summary here. All of these tools can help you when you probably just want a little more information than console.log(pet) and don’t need a debugger.

Perhaps the most useful is console.table, but the other methods have their own scenarios. I’m a big fan of console.assert when we want to debug something, but only in special cases.

If you find any mistakes in your translation or other areas that need to be improved, you are welcome to the Nuggets Translation Program to revise and PR your translation, and you can also get the corresponding reward points. The permanent link to this article at the beginning of this article is the MarkDown link to this article on GitHub.


The Nuggets Translation Project is a community that translates quality Internet technical articles from English sharing articles on nuggets. The content covers Android, iOS, front-end, back-end, blockchain, products, design, artificial intelligence and other fields. If you want to see more high-quality translation, please continue to pay attention to the Translation plan of Digging Gold, the official Weibo, Zhihu column.