Debugging With console.log Without Drowning in Output
console.log is the fastest way to see what your code is doing, until it prints 300 lines and you can't find the one that matters. Label your logs, log objects properly, use console.table and console.group, and clean up before you ship.
console.log is the fastest way to see what your code is actually doing. It's also the fastest way to bury the answer under 300 lines of output. The problem is rarely that you logged too little. It's that you logged values with no label, in a loop, and left them there. This tutorial is about logging so the output answers a question.
Skip ahead: If you already label your logs and use console.table, skip to "console.group and console.trace".
First, is console.log the right tool?
For "what is this value right here?", yes. It's quick and it works everywhere. For "why does this value change between line 10 and line 40?", the debugger in DevTools (a breakpoint) is often faster, because you can pause and look at everything at once. Use logs for quick checks. If you've added your fifth log to chase the same bug, switch to a breakpoint.
Always label what you log
This is useless after the second log:
const subtotal = 1250;
const discount = "100";
console.log(subtotal);
console.log(discount);
console.log(subtotal - discount);
1250
100
1150
Which number is which? Now with labels, and the type:
const subtotal = 1250;
const discount = "100";
console.log("subtotal:", subtotal, typeof subtotal);
console.log("discount:", discount, typeof discount);
subtotal: 1250 number
discount: 100 string
The second version just told you discount is a string, which is the bug waiting to happen the moment someone writes subtotal + discount.
A shortcut: wrap variables in braces and the name comes for free.
const subtotal = 1250;
const discount = "100";
console.log({ subtotal, discount });
{ subtotal: 1250, discount: '100' }
The quotes around '100' show it's a string. In the browser console, you'll see the same object with an arrow to expand it.
Logging objects: the snapshot trap
⚠ Warning: In the browser console, a logged object or array is shown live. If you change it after logging, then expand it in the console, you see the new values, not the ones at the moment you logged. When you need the value at that exact moment, log a copy: console.log(JSON.parse(JSON.stringify(cart))), or structuredClone(cart) in current browsers.
This trap makes people think their code changed something earlier than it did. If a logged object looks "already updated", suspect this first.
console.table for lists
An array of objects in a normal log is a wall of braces. console.table turns it into a table:
const cart = [
{ name: "Coffee", price: 95, qty: 2 },
{ name: "Ensaymada", price: 35, qty: 6 },
{ name: "Water", price: 20, qty: "1" },
];
console.table(cart);
In the browser you get columns for name, price and qty, one row per item. The "1" in quotes stands out next to the numbers. Try spotting that in raw output.
Don't log inside a big loop
Logging every round of a loop over 2,000 orders makes the console slow and the output unreadable. Log only what's interesting:
const orders = [500, 0, 1200, -50, 300];
for (const [i, amount] of orders.entries()) {
if (amount <= 0) {
console.log("suspicious order", { i, amount });
}
}
suspicious order { i: 1, amount: 0 }
suspicious order { i: 3, amount: -50 }
Other levels: warn and error
console.warn(...)shows in yellow.console.error(...)shows in red, with a stack trace.
Use them for things that are actually wrong, not for colour. The console's "Default levels" filter lets you hide plain logs and see only warnings and errors, which helps on a noisy page.
console.group and console.trace
console.group indents related logs under a heading you can collapse:
function applyVoucher(total, code) {
console.group("applyVoucher " + code);
console.log("total in:", total);
const result = code === "SAVE100" ? total - 100 : total;
console.log("total out:", result);
console.groupEnd();
return result;
}
applyVoucher(1250, "SAVE100");
applyVoucher SAVE100
total in: 1250
total out: 1150
console.trace("here") prints how the code got to that line: which function called which. Use it when a function runs and you don't know who called it.
Clean up before you ship
💡 Tip: Prefix temporary logs with something you can search for, like console.log("DBG", ...). Before you commit or publish, search the project for DBG and remove them all. It takes ten seconds.
Leftover logs aren't harmless. They slow down busy pages, they confuse the next person who opens the console, and they can print customer data, like an email address or an order, into any visitor's console. Logs are for you, while you're working. Not for production.
Common mistakes
- Logging values with no labels.
- Trusting an expanded object in the console to show the value at log time.
- Logging inside a loop over thousands of items.
- Leaving logs with personal data in live code.
So, think about the last bug you chased with console.log. How many of your logs had a label, and how long would it have taken with one?
About
How to use console.log with labels, objects, console.table, console.group and console.trace so the output answers your question. After this, you can debug from the console without scrolling through noise.
- Responsible
- Christopher R
- Last Update
- 08/30/2026
- Reading Time
- 5 min
Reviews
Sign in to write a reviewComments (0)
Sign in to commentNo comments yet.