Debugging JavaScript: 25 Console Tricks Most Developers Don't Know
console.log() is just the beginning. Here's what the console can really do.
The Basics (You Probably Know These)
console.log('Hello'); // Basic log
console.error('Oops'); // Red error
console.warn('Careful'); // Yellow warning
console.info('FYI'); // Blue info (in some browsers)
console.debug('Dev only'); // Hidden unless verbose mode
1. String Substitution
const user = 'Alex';
const score = 95;
// Old way (annoying)
console.log('User: ' + user + ' Score: ' + score);
// Better way
console.log('User: %s Score: %d', user, score);
// Output: User: Alex Score: 95
// ES6 template literals work too
console.log(`User: ${user} Score: ${score}`);
2. console.table() — Game Changer
const users = [
{ id: 1, name: 'Alex', role: 'admin', active: true },
{ id: 2, name: 'Sam', role: 'user', active: false },
{ id: 3, name: 'Jordan', role: 'user', active: true },
];
// ❌ Boring:
console.log(users); // Hard to read with many properties
// ✅ Beautiful table:
console.table(users);
Output:
┌─────┬────────┬─────┬────────┬────────┐
│ (idx)│ id │name │ role │ active │
├─────┼────────┼─────┼────────┼────────┤
│ 0 │ 1 │Alex │ admin │ true │
│ 1 │ 2 │ Sam │ user │ false │
│ 2 │ 3 │Jordan│ user │ true │
└─────┴────────┴─────┴────────┴────────┘
// Show specific columns only
console.table(users, ['name', 'active']);
3. console.group() — Organize Logs
function processOrder(order) {
console.group('📦 Order Processing');
console.groupInfo('Input:', order.id);
console.log(order);
console.groupEnd();
console.group('Validation');
console.log('Items:', order.items.length);
console.log('Total:', order.total);
console.log('Valid:', validate(order));
console.groupEnd();
if (order.items.length > 10) {
console.warn('Large order detected');
}
console.groupEnd(); // Closes "Order Processing"
}
// Collapsed by default:
// console.groupCollapsed('📦 Order Processing');
4. console.time() — Performance Measurement
// Simple timing
console.time('fetch');
await fetch('/api/data');
console.timeEnd('fetch');
// Output: fetch: 234.567ms
// Multiple timers
console.time('db-query');
const users = await db.query('SELECT * FROM users');
console.timeEnd('db-query');
console.time('render');
renderUsers(users);
console.timeEnd('render');
// Nested timers (shows hierarchy)
console.time('total');
console.time('step-1');
await step1();
console.timeEnd('step-1');
console.time('step-2');
await step2();
console.timeEnd('step-2');
console.timeEnd('total');
5. console.assert() — Conditional Logging
const value = getUserInput();
// Only logs when assertion fails
console.assert(value > 0, 'Value should be positive', { actualValue: value });
console.assert(user.isAdmin, 'Access denied for non-admin', user);
// Great for invariant checks in development:
function divide(a, b) {
console.assert(b !== 0, 'Division by zero!', { a, b });
return a / b;
}
6. console.count() and countReset()
function handleRequest(req) {
console.count('requests'); // Counts how many times called
// Output: requests: 1
// Output: requests: 2
// Output: requests: 3
if (req.method === 'POST') {
console.count('POST requests');
}
}
// Reset counter
console.countReset('requests');
7. console.trace() — Call Stack
function functionA() { functionB(); }
function functionB() { functionC(); }
function functionC() { console.trace('How did I get here?'); }
functionA();
// Output:
// Trace: How did I get here?
// at functionC (script.js:4)
// at functionB (script.js:3)
// at functionA (script.js:2)
// at <anonymous> (script.js:6)
Perfect for debugging "who called this function?"
8. console.dir() — Object Inspection
const element = document.body;
// console.log shows HTML-like representation
console.log(element);
// console.dir shows all properties/methods as expandable tree
console.dir(element);
// With depth option (useful for deeply nested objects)
console.dir(obj, { depth: null }); // Infinite depth
console.dir(obj, { depth: 2 }); // Only 2 levels
9. Styling Console Output
// Add CSS styles to console output
console.log(
'%c ERROR %c Something went wrong!',
'background: red; color: white; padding: 2px 8px; border-radius: 4px;',
'color: red; font-weight: bold;'
);
// Common patterns
console.log('%c SUCCESS', 'background: green; color: white; padding: 2px 6px; border-radius: 3px;');
console.log('%c WARNING', 'background: orange; color: white; padding: 2px 6px; border-radius: 3px;');
console.log('%c INFO', 'background: blue; color: white; padding: 2px 6px; border-radius: 3px;');
// Progress bar simulation
function showProgress(percent) {
const filled = Math.round(percent / 5);
const empty = 20 - filled;
console.log(`%c[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${percent}%`,
'font-family: monospace;');
}
showProgress(67); // ████████████████████░░░░ 67%
10. Clear and Copy
console.clear(); // Clears the console
// Copy to clipboard (Chrome/Edge)
copy(JSON.stringify(data)); // Copies to clipboard!
console.log('Data copied to clipboard!');
Advanced: Custom Logger
class Logger {
constructor(prefix, enableColors = true) {
this.prefix = prefix;
this.colors = enableColors;
}
_style(colorCode) {
return `color: ${colorCode}; font-weight: bold;`;
}
log(...args) {
console.log(`%c[${this.prefix}]`, this._style('#888'), ...args);
}
error(...args) {
console.error(`%c[${this.prefix}]`, this._style('red'), ...args);
}
success(...args) {
console.log(`%c[${this.prefix}] ✓`, this._style('green'), ...args);
}
timer(label) {
return {
start: () => console.time(`${this.prefix}:${label}`),
stop: () => console.timeEnd(`${this.prefix}:${label}`),
};
}
}
const db = new Logger('DB');
const api = new Logger('API');
db.timer('query').start();
// ... query ...
db.timer('query').stop(); // [DB]: query: 45ms
api.success('User created:', { id: 123 });
// Output: [API] ✓ User created: {id: 123}
Node.js Specifics
// console.dir with circular references
const obj = {};
obj.self = obj;
console.dir(obj, { depth: null }); // Handles circular refs gracefully
// util.inspect() for more control
const util = require('util');
console.log(util.inspect(obj, { colors: true, depth: null }));
// Error.stack for full trace
try { JSON.parse('{bad}') } catch(e) { console.error(e.stack); }
// process.memoryUsage()
console.log('Memory:', process.memoryUsage());
// { rss: 45678901, heapUsed: 12345678, heapTotal: 34567890, external: 1234567, arrayBuffers: 987654 }
Browser-Specific Tricks
// $0 = currently selected element in DevTools
// Type in console:
$0.style.color = 'red'; // Changes selected element's color
// $$(selector) = Array.from(document.querySelectorAll())
$$('.card').forEach(el => el.classList.add('highlight'));
// $_ = last evaluated expression
[1, 2, 3].map(x => x * 2); // [2, 4, 6]
$_; // [2, 4, 6]
// monitorEvents(element)
monitorEvents(window, 'click'); // Logs all click events
unmonitorEvents(window); // Stop monitoring
// queryObjects(Constructor) - find objects by type
queryElements(MyClass); // Lists all instances of MyClass
// getEventListeners(element)
getEventListeners(button); // Shows all event listeners on element
Quick Reference Card
| Method | Use For |
|---|---|
.log() |
General logging |
.error() |
Errors (red) |
.warn() |
Warnings (yellow) |
.table() |
Tabular data display |
.group() |
Grouping related logs |
.time/timeEnd |
Performance measurement |
.assert() |
Conditional logging |
.count() |
Count invocations |
.trace() |
Stack traces |
.dir() |
Deep object inspection |
%c styling |
Visual emphasis |
clear() |
Clean slate |
Which of these is your favorite? Any I missed?
Follow @armorbreak for more JavaScript tips.
Top comments (0)