Welcome to DRIXO — Your Coding Journey Starts Here
DRIXO Code • Learn • Build

How to Debug JavaScript Like a Pro

February 08, 2026 8 min read 0 Comments
How to Debug JavaScript Like a Pro
JavaScript

How to Debug JavaScript Like a Pro

DRIXO

Code · Learn · Build

If you've ever struggled with how to debug javascript like a pro, you're not alone. In this hands-on tutorial, I'll walk you through everything from the basics to real-world applications — with code you can actually use in your projects.

Console Methods Beyond console.log

Most developers only use console.log(), but the Console API has much more powerful tools:

// Structured data display
const users = [
  { name: 'Alice', age: 28, role: 'developer' },
  { name: 'Bob', age: 32, role: 'designer' },
  { name: 'Charlie', age: 25, role: 'developer' },
];
console.table(users);  // Beautiful table format!

// Group related logs
console.group('User Authentication');
console.log('Checking token...');
console.log('Token valid');
console.log('Loading user data...');
console.groupEnd();

// Timing operations
console.time('fetchData');
await fetch('/api/data');
console.timeEnd('fetchData');  // "fetchData: 142.5ms"

// Conditional logging
console.assert(users.length > 0, 'No users found!');  // Only logs if false

// Count occurrences
for (const user of users) {
  console.count(user.role);  // "developer: 1", "designer: 1", "developer: 2"
}

// Styled console output
console.log(
  '%c DRIXO Debug %c v1.0',
  'background: #00d4aa; color: #1a1a2e; padding: 4px 8px; font-weight: bold;',
  'background: #1a1a2e; color: #00d4aa; padding: 4px 8px;'
);

Breakpoints and the Debugger Statement

// Add breakpoints directly in code
function processOrder(order) {
  const total = order.items.reduce((sum, item) => sum + item.price, 0);

  debugger;  // Execution pauses here when DevTools is open

  if (total > 1000) {
    applyDiscount(order, 0.1);
  }

  return total;
}

// Conditional breakpoints (set in DevTools):
// Right-click a line number → "Add conditional breakpoint"
// Example: order.total > 500
// The breakpoint only triggers when the condition is true

Types of breakpoints in Chrome DevTools:

  • Line breakpoints — Click line number in Sources panel
  • Conditional breakpoints — Right-click line → Add conditional breakpoint
  • DOM breakpoints — Right-click element → Break on → subtree modifications
  • XHR/Fetch breakpoints — Sources → XHR/fetch Breakpoints → Add URL pattern
  • Event listener breakpoints — Sources → Event Listener Breakpoints → click, keyboard, etc.

Network Debugging

// Intercept and log all fetch requests
const originalFetch = window.fetch;
window.fetch = async function(...args) {
  const url = args[0];
  console.log(`🌐 Fetch: ${typeof url === 'string' ? url : url.url}`);
  console.time(`fetch-${url}`);

  try {
    const response = await originalFetch.apply(this, args);
    console.timeEnd(`fetch-${url}`);
    console.log(`  Status: ${response.status} ${response.statusText}`);

    // Clone response to read body without consuming it
    const clone = response.clone();
    clone.json().then(data => {
      console.log('  Response:', data);
    }).catch(() => {});

    return response;
  } catch (error) {
    console.timeEnd(`fetch-${url}`);
    console.error(`  Error: ${error.message}`);
    throw error;
  }
};

Error Tracking Patterns

// Global error handler
window.addEventListener('error', (event) => {
  console.error('Uncaught error:', {
    message: event.message,
    file: event.filename,
    line: event.lineno,
    column: event.colno,
    stack: event.error?.stack
  });
  // Send to error tracking service
  // reportError(event.error);
});

// Promise rejection handler
window.addEventListener('unhandledrejection', (event) => {
  console.error('Unhandled promise rejection:', event.reason);
  event.preventDefault(); // Prevent default console error
});

// Custom error classes for better debugging
class ValidationError extends Error {
  constructor(field, message) {
    super(`Validation failed for "${field}": ${message}`);
    this.name = 'ValidationError';
    this.field = field;
  }
}

class APIError extends Error {
  constructor(endpoint, status, body) {
    super(`API Error ${status} at ${endpoint}`);
    this.name = 'APIError';
    this.status = status;
    this.endpoint = endpoint;
    this.body = body;
  }
}

// Usage
try {
  throw new ValidationError('email', 'Invalid format');
} catch (e) {
  if (e instanceof ValidationError) {
    console.log(`Fix field: ${e.field}`);
  }
}

Performance Debugging

// Performance API for precise measurements
performance.mark('start-render');

// ... rendering logic ...

performance.mark('end-render');
performance.measure('render-time', 'start-render', 'end-render');

const measure = performance.getEntriesByName('render-time')[0];
console.log(`Render took: ${measure.duration.toFixed(2)}ms`);

// Memory debugging (Chrome only)
if (performance.memory) {
  console.log({
    totalJSHeap: (performance.memory.totalJSHeapSize / 1048576).toFixed(2) + ' MB',
    usedJSHeap: (performance.memory.usedJSHeapSize / 1048576).toFixed(2) + ' MB',
    heapLimit: (performance.memory.jsHeapSizeLimit / 1048576).toFixed(2) + ' MB'
  });
}

// Find slow functions with a simple profiler
function profileFunction(fn, label) {
  return function(...args) {
    const start = performance.now();
    const result = fn.apply(this, args);
    const duration = performance.now() - start;
    if (duration > 16) { // Longer than one frame (60fps)
      console.warn(`⚠️ ${label} took ${duration.toFixed(2)}ms (janky!)`);
    }
    return result;
  };
}

// Wrap any function to monitor its performance
const renderList = profileFunction(function(items) {
  // expensive rendering logic
}, 'renderList');

Debugging Checklist

When you hit a bug, follow this systematic approach:

  1. Reproduce consistently — Find the exact steps to trigger the bug
  2. Read the error message — Sounds obvious, but read every word
  3. Check the stack trace — Work backwards from the error
  4. Isolate the problem — Comment out code until the error stops
  5. Check your assumptions — console.log the values you think you know
  6. Search the error message — Stack Overflow has seen your bug before
  7. Take a break — Fresh eyes catch bugs faster than tired ones
Pro Tip: Use console.trace() to see the full call stack at any point in your code — it's incredibly useful for tracing where a function was called from.
AM
Arjun Mehta
Full-Stack Developer & Technical Writer at DRIXO

Full-stack developer with 5+ years of experience in Python and JavaScript. I love breaking down complex concepts into simple, practical tutorials. When I'm not coding, you'll find me contributing to open-source projects.

Comments