DEV Community

Alex Chen
Alex Chen

Posted on

How to Debug JavaScript Like a Pro

How to Debug JavaScript Like a Pro

Stop using console.log for everything. Here's a better way.

Level 1: console.log Done Right

// ❌ Bad: No context
console.log(data);
console.log(user);
console.log(error);

// ✅ Good: Labeled and structured
console.log('User data:', { id: user.id, name: user.name, role: user.role });
console.log('API response status:', res.status);

// ✅ Better: Console styling
console.log('🚀 App started');
console.log('⚠️ Warning: Rate limit approaching', { remaining: limit });
console.error('❌ Fetch failed:', error.message);

// ✅ Best: Table format for arrays/objects
const users = [{name:'Alex',age:30}, {name:'Sam',age:25}];
console.table(users);
// ┌─────────┬──────┬─────┐
// │ (index) │ name │ age │
// ├─────────┼──────┼─────┤
// │    0    │ Alex │ 30  │
// │    1    │ Sam  │ 25  │
// └─────────┴──────┴─────┘
Enter fullscreen mode Exit fullscreen mode

Level 2: Console Methods You Didn't Know About

// Group related logs
console.group('API Request');
console.log('URL:', url);
console.log('Method:', method);
console.log('Headers:', headers);
console.groupEnd();

// Assert (only logs if condition is false)
console.assert(user.age >= 18, 'User is underage:', user.age);
// Assertion failed: User is underage: 15

// Time operations
console.time('fetchData');
await fetchData();
console.timeEnd('fetchData'); // fetchData: 1.234s

// Count how many times something happens
function handleRequest(req) {
  console.count('requests'); // requests: 1, 2, 3...
}

// Trace the call stack
function process(data) {
  console.trace('process called');
  // Shows full stack trace of who called this function
}

// Dir: Inspect DOM elements or objects
console.dir(document.body);     // Full object properties
console.dirxml(element);        // XML/HTML representation
Enter fullscreen mode Exit fullscreen mode

Level 3: Chrome DevTools Breakpoints

// Don't modify code! Use DevTools instead:

// Regular breakpoint — click line number in Sources panel
debugger;                       // Programmatic breakpoint (remove before commit!)

// Conditional breakpoint — right-click → "Add conditional breakpoint"
// Enter: data.length > 1000
// Only pauses when condition is true!

// Logpoint — right-click → "Add logpoint"
// Enter: 'Processing item:', item.name
// Logs without pausing execution!

// DOM breakpoint — Elements panel → right-click element
// Break on: subtree modifications, attribute changes, node removal

// XHR/Fetch breakpoint — Sources panel → XHR breakpoints
// Add URL pattern: /api/users
// Pauses when any request matches this URL
Enter fullscreen mode Exit fullscreen mode

Level 4: Network Tab Mastery

When debugging API issues:

1. Open DevTools → Network tab
2. Reproduce the issue
3. Find the request in the list
4. Check:
   - Status code (200? 404? 500?)
   - Response headers (CORS? Content-Type?)
   - Response body (is it what you expected?)
   - Timing (DNS? TTFB? Download?)

Pro tips:
- Filter by type: XHR, JS, CSS, Img
- Filter by text: type in search box
- "Preserve log" to keep logs across page navigations
- "Disable cache" to test without cached responses
- Copy as cURL/fetch to reproduce programmatically
Enter fullscreen mode Exit fullscreen mode

Level 5: The Debugger Statement + Source Maps

// In your source code:
function complexCalculation(input) {
  debugger; // Execution pauses here when DevTools is open
  const result = input * 2;
  return result;
}
Enter fullscreen mode Exit fullscreen mode
DevTools workflow:
1. Open Sources panel
2. Find your file (or Ctrl+P to search)
3. Set breakpoints by clicking line numbers
4. Refresh page or trigger action
5. Use controls:
   - F8: Resume / Pause
   - F10: Step over (don't go into functions)
   - F11: Step into (go inside functions)
   - Shift+F11: Step out (exit current function)

6. Watch panel: Add expressions to monitor
7. Scope panel: See current variables
8. Call Stack: See how you got here
Enter fullscreen mode Exit fullscreen mode

Level 6: Performance Profiling

// Performance tab:
// 1. Click Record (or Ctrl+E)
// 2. Do the thing you want to measure
// 3. Stop recording
// 4. Analyze the flame chart

// Common findings:
// - Long tasks (>50ms) cause jank
// - Layout thrashing (read/write/read/write DOM)
// - Memory leaks (growing heap over time)
// - Unnecessary re-renders

// Memory tab:
// 1. Take heap snapshot
// 2. Do actions that might leak
// 3. Take another snapshot
// 4. Compare snapshots to find leaked objects
Enter fullscreen mode Exit fullscreen mode

Common Bugs & How to Find Them

"undefined is not a function"

// Cause: Calling something that doesn't exist
user.getName(); // getName is undefined

// Fix: Check what you're calling
console.log(typeof user.getName); // "undefined"?
console.log(user);               // Is user what you expect?
Enter fullscreen mode Exit fullscreen mode

"Cannot read property of undefined"

// Cause: Chaining on possibly undefined value
data.user.address.city;

// Fix: Optional chaining
data?.user?.address?.city;       // Returns undefined instead of crashing

// Or destructure with defaults
const { city = 'Unknown' } = data?.user?.address ?? {};
Enter fullscreen mode Exit fullscreen mode

"TypeError: X is not a function"

// Cause: Variable shadows a function name
const fetch = 'not a function';
fetch('/api/data');             // TypeError!

// Fix: Name things differently
const fetchUrl = '/api/data';
fetch(fetchUrl);
Enter fullscreen mode Exit fullscreen mode

Race Condition

// Cause: Async operation completes out of order
let userId;
fetchUser().then(u => { userId = u.id });
loadData(userId);              // userId might still be undefined!

// Fix: Chain properly
fetchUser()
  .then(u => loadData(u.id))
  .catch(err => console.error(err));
Enter fullscreen mode Exit fullscreen mode

The Debugging Checklist

When something breaks:

1. Reproduce it consistently
2. Read the error message carefully
3. Check the line number and file
4. Verify assumptions (what IS the value of this variable?)
5. Simplify (comment out code until it works)
6. Check recent changes (git diff)
7. Search for the error message online
8. Ask: What changed since it last worked?
9. Check browser console AND server logs
10. Clear cache and cookies (sometimes it's that simple)
Enter fullscreen mode Exit fullscreen mode

What's your favorite debugging technique? Share it below!

Follow @armorbreak for more developer content.

Top comments (0)