JavaScript Debugging
Debugging is the process of finding and fixing errors in your code. JavaScript provides several tools and techniques for debugging, from simple console methods to powerful browser DevTools.
console.log() and Friends
The console object has many methods beyond log(). Using the right method helps you organize and filter debugging output.
// Basic logging
console.log('Simple message');
console.log('Value:', 42, 'Type:', typeof 42);
// Warnings (yellow in browser console)
console.warn('This is a warning');
// Errors (red in browser console)
console.error('This is an error message');
// Info
console.info('Informational message');
// String substitution
console.log('Hello %s, you are %d years old', 'Alice', 30);
// Styled output (browser only)
console.log('%cStyled text', 'color: blue; font-size: 20px');console.table() and console.dir()
console.table() displays tabular data in a formatted table, making arrays and objects much easier to read. console.dir() displays an interactive list of object properties.
// Display array of objects as table
const users = [
{ name: 'Alice', age: 30, role: 'admin' },
{ name: 'Bob', age: 25, role: 'user' },
{ name: 'Charlie', age: 35, role: 'user' }
];
console.table(users);
// Display specific columns
console.table(users, ['name', 'role']);
// Display a single object
const config = { host: 'localhost', port: 3000, debug: true };
console.table(config);
// console.dir() for deep object inspection
const nested = { a: { b: { c: 42 } } };
console.dir(nested, { depth: null });Grouping and Timing
Console groups help organize related log messages, and timing methods help measure code performance.
// Grouping related messages
console.group('User Processing');
console.log('Loading users...');
console.log('Found 3 users');
console.log('Processing complete');
console.groupEnd();
// Collapsed group (starts closed in browser)
console.groupCollapsed('Details');
console.log('Detail 1');
console.log('Detail 2');
console.groupEnd();
// Timing code execution
console.time('array-creation');
const arr = Array.from({ length: 100000 }, (_, i) => i);
console.timeEnd('array-creation');
// array-creation: 5.123ms
// Count how many times something happens
for (let i = 0; i < 3; i++) {
console.count('loop iteration');
}
// loop iteration: 1
// loop iteration: 2
// loop iteration: 3The debugger Keyword
The debugger statement pauses code execution and opens the browser's debugging tools (if available). It acts like a programmatic breakpoint.
function calculateTotal(items) {
let total = 0;
for (const item of items) {
// Execution pauses here when DevTools is open
debugger;
total += item.price * item.quantity;
}
return total;
}
const items = [
{ name: 'Widget', price: 10, quantity: 3 },
{ name: 'Gadget', price: 25, quantity: 1 }
];
const total = calculateTotal(items);
console.log('Total:', total); // Total: 55Browser DevTools and Breakpoints
Browser Developer Tools (F12 or Ctrl+Shift+I) provide the most powerful debugging experience. The Sources panel lets you set breakpoints, step through code, and inspect variables.
| DevTools Feature | Description | Shortcut |
|---|---|---|
| Breakpoint | Pause execution at a specific line | Click line number in Sources |
| Conditional Breakpoint | Pause only when condition is true | Right-click line number |
| Step Over (F10) | Execute current line and move to next | F10 |
| Step Into (F11) | Jump into function call | F11 |
| Step Out (Shift+F11) | Finish current function and return | Shift+F11 |
| Watch Expressions | Monitor variable values as you step | Add in Watch panel |
| Call Stack | See the chain of function calls | Call Stack panel |
| Console | Execute code in current scope while paused | Console panel |
// Strategy 1: Isolate the problem
function processOrder(order) {
console.log('Input order:', JSON.stringify(order));
const subtotal = order.items.reduce((sum, item) => {
const lineTotal = item.price * item.qty;
console.log(` ${item.name}: $${lineTotal}`);
return sum + lineTotal;
}, 0);
console.log('Subtotal:', subtotal);
return subtotal;
}
const order = {
items: [
{ name: 'Book', price: 15, qty: 2 },
{ name: 'Pen', price: 3, qty: 5 }
]
};
console.log('Total:', processOrder(order));
// Book: $30
// Pen: $15
// Subtotal: 45
// Total: 45
// Strategy 2: Use assertions
function divide(a, b) {
console.assert(b !== 0, 'Divisor should not be zero!');
return a / b;
}
console.log(divide(10, 2)); // 5
divide(10, 0); // Assertion failed: Divisor should not be zero!