Published May 30, 2026 ยท 9 min read ยท ๐Ÿท๏ธ JavaScript

Debugging JavaScript: Professional Techniques

Every developer spends more time debugging than writing new code. This guide covers the techniques and tools that make debugging efficient and even enjoyable.

Console Beyond console.log

Most developers know console.log, but there are more powerful methods:

// Group related logs
console.group('User Data');
console.log('Name:', user.name);
console.log('Email:', user.email);
console.groupEnd();

// Styled logging
console.log('%cStyled Text', 'color: red; font-size: 20px');

// Table for arrays/objects
console.table(users);

// Trace call stack
console.trace('Called from:');

// Assert (only logs if condition is false)
console.assert(user.name, 'User name is missing!');

// Time operations
console.time('fetchData');
fetch('/api/data').then(() => console.timeEnd('fetchData'));

Browser DevTools: Sources Panel

The Sources panel is where breakpoints live. Key features:

  • Set breakpoints on lines, conditions, or exceptions
  • Step through code line by line
  • Watch variables and expressions
  • Inspect scope variables
  • Call stack navigation

Opening DevTools: F12 or Cmd+Option+I (Mac) / Ctrl+Shift+I (Windows)

Breakpoint Types

Line Breakpoints

Click the line number in the Sources panel. Execution stops before that line runs.

Conditional Breakpoints

// Right-click line number โ†’ "Add conditional breakpoint"
// Only pauses when condition is true
user && user.id === 123

Logpoints (Chrome)

// Right-click line โ†’ "Add logpoint"
// Logs to console without stopping execution
console.log('User updated:', user.name)

XHR Breakpoints

Break when specific network requests are made. Right-click in Network tab โ†’ "Break on โ†’ Response"

The Debugger Statement

Add debugger; directly in your code:

function processUser(userData) {
  const processed = transformData(userData);
  debugger;  // Pauses here when DevTools open
  return saveUser(processed);
}

Useful for specific issues that are hard to reproduce, or for debugging in production (though consider using error tracking services instead).

Network Debugging

The Network tab shows all requests. Use it to:

  • Check request/response payloads
  • Verify headers are sent correctly
  • Measure request timing
  • Find slow requests (Waterfall view)
// Copy as fetch/cURL to replay requests
// Right-click request โ†’ Copy โ†’ Copy as Fetch

Common Bugs and How to Find Them

Asynchronous Bugs

// Bug: Closures with loops
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// Logs: 3, 3, 3 (var is function-scoped)

// Fix 1: Use let
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// Logs: 0, 1, 2

// Fix 2: Closure with IIFE
for (var i = 0; i < 3; i++) {
  ((j) => setTimeout(() => console.log(j), 100))(i);
}

Null Reference Errors

// Bug: Not checking for null/undefined
const name = user.profile.displayName;
// Fails if user or profile is undefined

// Fix: Optional chaining
const name = user?.profile?.displayName ?? 'Anonymous';

// Or explicit check
const name = user && user.profile && user.profile.displayName;

Mutation Bugs

// Bug: Mutating shared state
function addItem(items, newItem) {
  items.push(newItem);  // Mutates original array!
  return items;
}

// Fix: Create new array
function addItem(items, newItem) {
  return [...items, newItem];  // Immutable
}

Professional Tips

1. Binary Search with Comments

// When you don't know where the bug is
console.log('Checkpoint 1');
// Part 1 of code
console.log('Checkpoint 2');
// Part 2
console.log('Checkpoint 3');
// Narrow down until you find it

2. Compare with a Working State

// When did it stop working?
// Git bisect helps find the exact commit
git bisect start
git bisect bad  # current is broken
git bisect good abc123  # this commit worked
# Git tests commits automatically

3. Rubber Duck Debugging

Explain your code line-by-line to a rubber duck (or coworker). The act of explaining often reveals the issue.

4. Reproduce in Minimal Environment

Copy the problematic code into a fresh HTML file or CodePen. Strip away everything except what's needed to reproduce the bug.

Production Debugging

For production bugs, you can't just open DevTools. Use:

  • Error tracking: Sentry, Bugsnag, LogRocket
  • Logging: Structured logs to cloud services (Datadog, CloudWatch)
  • Session replay: See what users did before the error
  • Source maps: Debug production code with readable variable names
// Example: Sentry error tracking
import * as Sentry from '@sentry/browser';
Sentry.init({ dsn: 'your-dsn' });
// Now all uncaught errors are captured with stack traces

VS Code Debugger

Debug without leaving your editor:

// 1. Install "Debugger for Chrome" extension
// 2. Add launch config to .vscode/launch.json
{
  "type": "chrome",
  "request": "launch",
  "name": "Launch Chrome",
  "url": "http://localhost:3000",
  "webRoot": "${workspaceFolder}"
}
// 3. Press F5 to start debugging
// 4. Set breakpoints in VS Code

Quick Reference

Command Action
F8Resume execution
F10Step over (skip function)
F11Step into (enter function)
Shift+F11Step out (exit function)
โ† Back to Blog
Copied!