Hacker News new | past | comments | ask | show | jobs | submit login
Advanced console.log Tips and Tricks (2020) (medium.com/nmc-techblog)
260 points by sidcool on June 15, 2021 | hide | past | favorite | 72 comments



Not directly console.log related, but you can use the console-only monitorEvents() method to log all the events triggered on an element:

https://developers.google.com/web/updates/2015/05/quickly-mo...

Very useful when you are wiring events together on the front end.

Surprised there isn’t a standard way to do this in the DOM.


You can also use monitor(func), debug(func) and inspect(func) and more :) https://developer.chrome.com/docs/devtools/console/utilities...


My favorites:

- `$0` to refer to last selected DOM node

- `copy(obj)` to copy something to clipboard (that might be hard to copy manually; for example long strings are often cut when selecting manually for copying)


`copy(JSON.stringify(foo))` is something I use all the time for pulling large objects into a text editor for easy browsing and searching.


$r is great if you have the react dev tools installed.


I used a bookmarklet on chrome

> javascript:(function(){console.log("monitor event"); window.addEventListener('message', (e) => {console.log(e);});})();

that way I can click the bookmark and start monitoring events whenever I want


I did not know this. Thanks!


This is amazing, does it point to the event handler as well?


> Not directly console.log related

Don't worry, neither is the article. Words don't mean much I guess.


A small extra trick:

If you use arrow functions without a body you can log and fallback to the original statement.

Example starting point, you're wondering what message is. ``` const upperCase = (message) => message.upperCase() ```

Don't add a body, just log and continue:

``` const upperCase = (message) => console.log(message) || message.upperCase() ```


That will work, because console.log() returns undefined.

It is a bit subtle for my taste, though. My suggestion for clarity is to go ahead and make the function have a body with {}:

  const upperCase = (message) => {
    console.log(message);
    return message.upperCase();
  };
Of course you may disagree, but no argument there, as I said it's a matter of taste.

(BTW backticks, either triple or single, do not work on HN. Indent by two spaces if you want code formatting.)


Yeah, I'm working on the assumption that this code is not committed but for a quick debug.

Any code that is shared shouldn't rely on that, I agree.

Thanks for the tip!


Since most of the times I want "a quick debug" I'm already on my browser and quite probably with the dev tools already open, I prefer right-clicking on a line and using "Add Log" (in Firefox) or "Add logpoint" (in Chrome-based browsers). It avoids having to modify the source and then clean it up when I'm done.


You can also use the comma operator: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...

`const upperCase = (message) => (console.log(message), message.upperCase())`

The function body needs to be in parens. Maybe not the most useful for this case, but I've used this when setting logpoints in Chrome to log a variable and save it to a global for further inspection.


Yes, useful when trying to debug functional style chaining:

  const result = array
    .map(someFunction)
    .filter(someOtherFunction)
    .map(x => (console.log(x), x)) // debug here
    .map(stillAnotherFunction);


I do something similar in React too:

const foo = () => console.log && <Something />

That stops the body rendering, and you can use '||' if you want the body and the log.


I should remember that one, I use a lot of console.log debugging still.


My dumb dead-simple trick that you've probably independently invented yourself: when I want to log variables x,y,z I write

console.log({x,y,z})

not

console.log(x,y,z)

Who needs pretty-printing, formatting libraries, string interpolation etc?


Yep, I have "invented" this myself as well :)


And the old version with json.stringify


Same here.


Practically every time I do a 'console.log' to see the value of something in the current page state I actually wanted a 'debugger' statement instead. Pausing execution so I can look at other things around what I wanted to log often proves very useful and let's me get to the root cause of a problem faster.


Are you lamenting that you reach for `console.log` first, instead of using the `debugger` statement, or are you wishing there was a `debugger` statement, because there absolutely is a `debugger` statement. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe...


I'm lamenting that I reach for console.log first and then regret it. Every single time.


Huh, why do you think you do that? Do you forget about the debugger statement, or is there some other reason you think console logging might work well?


Maybe my debugger skills aren't strong enough, but I find that when I'm trying to reason about how some complicated code is executing, a debugger statement forces me to wade through tons of internals in libraries I don't care about. Some well-placed console logs give me much less information overload.


The same here, also in my case at least 90% of the time when there is a problem I know where the problem is I just need to look at a couple things and confirm which of a couple scenarios could be causing the problem.


This is really missing at the moment.

I wish there was a "debugger snapshot" functionality that does not pause execution and creates a snapshot of the current DOM and state.

Probably a performance nightmare but being able to continue and inspect what happened in retrospect is what makes console.log a powerful debugging tool IMO.

You could extrapolate this to the time-traveling debuggers we've seen for Redux and other tools. That stuff is super powerful.


Interesting. I feel the opposite. Reading through multiple log lines somehow tells me something about the problem (program) that I don’t get when I use the debugger.


console.log(JSON.stringify(myValue, null, 2)) could be what you are looking for.


That's just a prettier console log. I almost always want to use the debugger.


What pains me that browsers no longer put blue icon with console.info. Like, what's the point of having it if it's going be virtually indistinguishable from .log?

It annoying.


Linters actually consider .log to be an error nowadays by default. They only accept debug/info/warn/error.

I take advantage of this so that my .log lines are stuff I need while developing but they shouldn't get committed, that's what the actual named log lines are for.


Firefox shows a little “i” in a circle to signify “info” but it’s subtle and I didn’t realize what it was for a long time.


You can filter the console by info/debug/warn/error which makes info pretty useful imo.


Something useful about logging that maybe not everyone knows about:

If you can't or don't want to pollute your code with `console.log` for debugging (can't edit original code; too long to rebuild; etc.):

You can add "log points" (Chrome and Firefox at least) directly in source view of devtools at specific lines of code

https://www.thedevelobear.com/post/logpoints/

You can also use "conditional breakpoint" to do conditional logging with `console.log`, again, without leaving devtools.


One thing to watch out is that console.log is asynchronous.

If the objects to be printed change between console.log() and the actual printing, the output you see may not represent the state when console.log() was called.


console.log is not asynchronous. For example, this code:

  let a = "hello";
  console.log( a );
  let a = "goodbye";
will always reliably print "hello", not "goodbye".

What you're referring to is the fact that when you expand an object or array in the console, then you see the contents of that object or array at the time you expand it, not as it originally existed when console.log() was called.

This is why alessioalex's sibling comment is so useful. By logging the output from JSON.stringify(), you are logging a string whose value will not change.


That's... what asynchronous means. The call to console.log() will return before the console output is actually produced.


No. It means that when you invoke `console.log` in a browser it "logs" a reference to an object instead of serialising it.

This log is still synchronous, but when you expand it in the console its properties are dereferenced and may be different from when the original log was made. The log, however, is still instantaneous and synchronous.


OK, agreed. That's an important distinction. The console log will synchronously receive a reference to an object; later if you expand something in the log window it shows you the current state.


I would say the argument is lazy evaluated.


To add to the MatthewMob's explanation, see this: https://imgur.com/a/vUTCumu


Thanks! I figured it meant that, but nice to see it without having to mess around.


Very useful advice. In those situations if you're trying to log an object just do `JSON.stringify(obj, null, 2)` to be sure of the state at that time.


I spent too long on one occasion trying to figure out why my logs looked like they were in the wrong order for a NodeJS application.

It was because one message was console.info and another was console.error, which was going to stderr and so getting flushed differently.

A couple months ago I fell for it again.


Nonsense. Console.log does not accept a callback and does not return any promise, therefore it's expected to work synchronously.


you're being ironic, right?


Nope, sarcastic.

If JavaScript devs don't know if a function is async or sync it just gives more evidence that JS is a monkey-language. LOL!


Not a "JavaScript dev", but I think JS is a fine language. Perhaps I'm biased, because I like Scheme. The browser environment is the shitshow.

A function can call a third party service, or some subsystem running on the same computer, whatever. Regardless of the programming language, that service may or may not do stuff asynchronously after your call. There's no way to tell. I regard the console.log to be a third party service. Who the heck knows what it does, except it has access to your memory!


I don't think you can compare JS to Scheme, I've heard of that meme though. Also, JS suffers from a lot of fragmentation in tooling and frameworks, so the problem is not just the language.

As for a third party service argument, you're just stretching the goal posts there to fit your argument.


It's not just a meme, JS was literally inspired by Scheme (garbage collection, lexical scoping, type system) and Java (some superficial syntax) and Self (object orientation).

I agree that the core language is not the worst problem with JS; that's what I was trying to say.

Regarding the other point about knowing whether something is async or not. Few languages will tell you if a function does side effects. They might spawn threads or processes, mutate the data you sent them, all after the call has returned. Languages where you can easily see that this will happen are few and far between, and they have strong static type systems.


I've created a collection of 200+ tips like this on my website: https://umaar.com/dev-tips/


It mentions the CSS-styling formatting specifier, but skips over the more mundane "printf-style" ones.

const obj = {objection: 'overruled'}; console.log( 'console.log is the #%d %s API ever written %f\% no arguing! %o %O !!!', 1, 'greatest', 100, obj, obj);

I've tried to keep my example compliant but it's still a very tiny loosy-goosy standard, for example at least in Firefox you can write %.0f to skip printing the fractional part of the float, but the standard doesn't mention this.


console.time{,Log,End} take an optional argument to label the timers, changing the "default" text to the label but also allowing multiple timers running simultaneously


An historic problem with logging is that if you wanted to create a logging library, every time you logged you would lose the line number of the log statement as it would just show that of the library rather than the call point.

This is solved by separating out your log library into a separate file, and then blackboxing it. Voila, original call points are preserved making debugging easier and your logs more useful.


This boys never read MDN


Haven't seen this mentioned, but here's one:

const dog = { name: "Dog" }

console.log(dog) VM287:1 {name: "Dog"}

console.log({dog}) VM305:1 {dog: {…}}dog: {name: "Dog"}__proto__: Object


What did you mean to emphasize here? Cos what I'm seeing is the language feature (ES6's "shorthand properties"), not something inherent to `console`.


The second example effectively prints an object with it's name. I often have multiple console.log statements and by utilizing that I know what each one is referring to just by typing 2 more characters.

EDIT: perhaps a better description by someone else https://news.ycombinator.com/item?id=27524164


console.dir does the same thing as console.log in every modern browser. I'm tired of seeing this "tip", and it's a pretty clear indication the article is poorly researched, the only difference is that it pre-expands the object.


console.table() is a favorite of mine for a variety of reasons, but one of the most important to me is that it's really easy to quickly find a giant table in a wall of text if I'm logging a bunch of other stuff.


For this I use console.error (red) or console.warn (yellow).


Wow, group/groupEnd is a life changer!


"upgrade to see more" paywalled story...


The google cache doesn't have a paywall


If it's not on all the browsers, please don't use any of this shit. Every time you use a chrome-specific browser you encourage the eventual death of all the non-chromium browsers which might be great for you right now, but is bad for the ecosystem in the long term.

Also, please stop writing tech blogs on medium. That well paid tech people of all people would be constrained to a paywall-middleman is an indictment of our entire field.


All the shit is cross-browser supported


Also, none of this stuff should ever be used in production code, only during development (at least IMHO). So even if some things were browser specific, it shouldn't hurt anyone but yourself if you run into incompatibilities while using any of it.


Is there any web standard mandating support of console API?


console.table doesn't work in IE6

DON'T YOU FEEL STUPID NOW?!


Awesome, glad that's the case. Guess I have to hold my breath for a future where technologists stop putting their knowledge behind paywalls then.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: