DEV Community

Cover image for Stop Using `console.log` — These Debugging Tricks Will Blow Your Mind
Josh Lawson
Josh Lawson

Posted on

Stop Using `console.log` — These Debugging Tricks Will Blow Your Mind

Let’s face it: console.log is the comfort food of debugging. It’s quick, familiar, and kind of satisfying in that junk-food sort of way. But if you've ever buried your terminal in a jungle of console.log("HERE"), console.log("THERE"), and the classic console.log("WTF is going on"), then you already know — it doesn’t scale.

Here’s the thing: if you're building real software (not just tinkering on a rainy Sunday), you need sharper tools. Tools that let you see what's happening under the hood without littering your codebase with digital breadcrumbs.

So yeah, it’s time to break up with console.log. But don’t worry — I’m not gonna leave you hanging. Let’s look at some smarter, dare I say, mind-blowing ways to debug your code without turning your terminal into a cry for help.


But First… Why Do We Cling to console.log?

Honestly? Because it works. It’s there. It’s easy. You don’t need to configure anything, and the feedback is immediate. It’s like that friend who gives you bad advice, but at least they answer your calls.

The problem is — it doesn’t help you think. It doesn’t offer context. It’s noisy. It’s often too much or too little. And worst of all, it turns your code into a mess of cluttered print statements that never get cleaned up. (And yes, you will forget one and push it to production.)

So let’s talk about real tools.


1. Set Breakpoints Like a Grown-Up (Seriously)

Debuggers aren’t just for Java or C++ elitists. In modern environments — think VS Code, Chrome DevTools, WebStorm — breakpoints are stupidly easy to use.

Here's how this works in practice:

  • Open your file in VS Code.
  • Click next to the line number. Boom — that’s a breakpoint.
  • Run your app in debug mode.
  • Execution stops right there. You can hover over variables, peek into scopes, even change values on the fly.

It’s like hitting “pause” on your code mid-movie. Want to see what user.isLoggedIn actually contains right there? Done. No need to type console.log('isLoggedIn:', user.isLoggedIn) five lines in a row.

And if you’re in the browser? Same deal. Open Chrome DevTools → Sources tab → click the line number. You're in.

Honestly, once you start using breakpoints properly, going back to console.log feels like debugging with a blindfold and a stick.


2. Watch Expressions (a.k.a. X-Ray Vision for Variables)

Imagine if you could track a variable’s value as your code runs — without manually logging it every time it changes.

That’s what watch expressions do.

In your debugger panel (again, VS Code or Chrome DevTools), there’s usually a section called Watch. Add a variable name, like cart.total or this.state.user. Now, every time you hit a breakpoint, you get an updated snapshot of its current value — no print statements, no noise, just insight.

Bonus tip? You can even write little expressions like userList.filter(u => u.isAdmin) — and it’ll evaluate them live.

If console.log is a flashlight in the dark, watch expressions are night-vision goggles.


3. Conditional Breakpoints (a.k.a. “Only Stop When It’s Weird”)

Here’s a scenario: you're in a loop that runs 1,000 times, and you only care about the 437th iteration when things blow up. You don’t want to slog through the first 436 steps, right?

Just right-click on your breakpoint and set a condition like i === 437.

Now your code runs normally — until the exact moment something gets weird. You can even go fancier:

user.role === 'admin' && user.isActive === false
Enter fullscreen mode Exit fullscreen mode

Feels like cheating. It kind of is. Use it anyway.


Leverage the Power of debugger; (Yup, It’s a Real Keyword)

This one's criminally underused. If you're in JavaScript land, you can literally type debugger; in your code. When DevTools is open, your app will pause there like you set a breakpoint — no clicking required.

It’s like planting a trap in your code. Want to pause right inside an anonymous callback? Or deep in a dynamic component? Drop a debugger; and let it stop on its own terms.

Just — and I’m begging you here — don’t leave it in your commits. 🙃


5. The Network Tab Is Your Best Friend

Raise your hand if you've ever tried to debug a bug that wasn't yours.

You’re calling some API. It returns… something. Maybe. Or it fails mysteriously. Or the payload is missing one tiny field that throws everything off.

Stop guessing. Just hit Network in your browser's DevTools.

  • You can see the full request and response.
  • Headers, payload, status codes.
  • Even how long it took.

It’s like calling the restaurant and asking, “Hey, what did you actually put in my order?” Then they send you the receipt and a recording of the kitchen.


6. Step Through Code Like Sherlock Holmes

Instead of logging ten things in a row, how about just… walking through the code?

Use Step Over, Step Into, and Step Out in your debugger to:

  • Move one line at a time (Step Over)
  • Jump inside a function call (Step Into)
  • Bail out of that function (Step Out)

It’s like flipping pages in a mystery novel — but you’re also the detective.

Once you get used to stepping through functions, you’ll catch weird async bugs, silent fails, and logic errors that logs just can’t show you.


7. Use Logging Libraries (If You Must Log)

Okay, okay. Sometimes you need to log.

But at least do it with style. Use libraries like:

  • debug: Enables you to toggle logs by namespace (e.g. DEBUG=auth:* node app.js)
  • winston: For serious, production-level logging with levels, formats, and transports.
  • pino: Ridiculously fast logger for Node.js apps.

These tools make logs meaningful. You get timestamps, categories, and the ability to turn logs on or off without editing your code.

Think of it like upgrading from Post-It notes to a whiteboard wall with color-coded markers.


8. Embrace Time Travel Debugging (Yes, That’s a Thing)

Instead of this:

console.log('Something broke')
Enter fullscreen mode Exit fullscreen mode

Try this:

console.trace('Something broke')
Enter fullscreen mode Exit fullscreen mode

It prints a full stack trace — so you see where that line was called, and who called it before that.

Especially handy when dealing with callbacks, async flows, or when your app feels like a spaghetti monster with 14 limbs and no memory.


10. Stop Blaming Yourself — Use Linters and Type Systems

Let’s be real: not every bug is a logic bug. Sometimes, it’s a typo. Or a missing prop. Or an undefined variable that only crashes under specific conditions.

You shouldn’t have to debug those. That’s what static analysis is for.

  • Use TypeScript to catch type mismatches before you run anything.
  • Use ESLint with solid rule sets to catch sneaky mistakes (like unused vars, unreachable code, or accidentally shadowed variables).

Less time debugging dumb stuff means more time fixing real stuff.


Final Thought: Tools Don’t Make You Lazy — They Make You Smart

There’s this weird macho culture in dev sometimes — like if you’re not suffering, you’re not doing it right. Forget that.

The best developers aren’t the ones who suffer through a thousand logs to track a bug — they’re the ones who build tools, understand systems, and use every trick at their disposal to get the job done faster and better.

You don’t get a gold star for sticking to console.log. You get clean code, saved time, and fewer headaches by working with the tools, not against them.

So go ahead — delete those logs. Set a breakpoint. Watch your variables like a hawk. Debug like you actually like your job.

Because you know what? You probably do.

- Josh

Top comments (0)