Lesson 27 of 30

Debugging Techniques

Finding and Fixing Bugs

Debugging is the process of finding and fixing errors (bugs) in your code. Every developer spends significant time debugging.

Modern browsers provide powerful developer tools including console logging, breakpoints, step-through debugging, and performance profiling.

Learning effective debugging techniques is essential for becoming a productive developer and solving problems efficiently.

Example
// Console methods for debugging
console.log('Basic log message');
console.info('Informational message');
console.warn('Warning message');
console.error('Error message');

// Log multiple values
const user = { name: 'Alice', age: 30 };
console.log('User:', user);

// console.table for arrays and objects
const users = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 }
];
console.table(users);

// console.time for performance measurement
console.time('operation');
// ... some code ...
console.timeEnd('operation'); // Logs: "operation: 1.23ms"

// console.assert for testing conditions
const age = 15;
console.assert(age >= 18, 'User must be 18 or older!');

// console.group for organizing logs
console.group('User Details');
console.log('Name:', user.name);
console.log('Age:', user.age);
console.groupEnd();

// Debugger statement (pauses execution in dev tools)
function complexFunction(data) {
  debugger; // Execution will pause here if dev tools open
  const result = processData(data);
  return result;
}

// Stack trace
console.trace('Show call stack');
  • console.log() - Most basic debugging tool, print values
  • console.table() - Display arrays/objects as tables
  • console.time/timeEnd() - Measure code execution time
  • console.assert() - Log error if condition is false
  • debugger statement - Pause execution in browser dev tools
  • Breakpoints - Set in browser to pause at specific lines
  • Step through - Execute code line by line in debugger
  • Watch expressions - Monitor variable values in real-time
Try Debugging Techniques
HTML
<div class="debug-demo">
  <h3>Debugging Examples</h3>
  <p><em>Open your browser's Developer Tools (F12) to see console output!</em></p>

  <div class="example">
    <h4>1. Console Methods</h4>
    <button id="consoleBtn">Run Console Examples</button>
    <div id="consoleInfo">Check the browser console (F12) for output</div>
  </div>

  <div class="example">
    <h4>2. Performance Timing</h4>
    <button id="timingBtn">Measure Performance</button>
    <div id="timingOutput"></div>
  </div>

  <div class="example">
    <h4>3. Bug Hunter</h4>
    <p>This code has a bug! Click to run and check the console for errors.</p>
    <button id="buggyBtn">Run Buggy Code</button>
    <button id="fixedBtn">Run Fixed Code</button>
    <div id="bugOutput"></div>
  </div>
</div>
CSS
.debug-demo {
  padding: 20px;
  max-width: 700px;
}

.debug-demo > p {
  background: #fff3e0;
  padding: 10px;
  border-left: 4px solid #ff9800;
  margin-bottom: 20px;
  border-radius: 4px;
}

.example {
  margin: 20px 0;
  padding: 15px;
  background: #f5f5f5;
  border-radius: 8px;
}

h4 {
  margin-top: 0;
  color: #333;
}

button {
  padding: 10px 15px;
  margin: 5px;
  background: #2196F3;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
}

button:hover {
  background: #1976D2;
}

#fixedBtn {
  background: #4CAF50;
}

#fixedBtn:hover {
  background: #45a049;
}

#consoleInfo, #timingOutput, #bugOutput {
  margin-top: 10px;
  padding: 12px;
  background: white;
  border: 2px solid #ddd;
  border-radius: 4px;
  font-family: 'Courier New', monospace;
  font-size: 13px;
  min-height: 40px;
}

.success {
  border-color: #4CAF50 !important;
  background-color: #e8f5e9 !important;
}

.error {
  border-color: #f44336 !important;
  background-color: #ffebee !important;
  color: #c62828;
}
JavaScript
// Example 1: Console Methods
document.getElementById('consoleBtn').addEventListener('click', function() {
  console.clear();
  console.log('=== Console Methods Demo ===');

  // Different log levels
  console.log('๐Ÿ“ Regular log message');
  console.info('โ„น๏ธ Information message');
  console.warn('โš ๏ธ Warning message');
  console.error('โŒ Error message');

  // Logging objects
  const user = {
    name: 'Alice',
    age: 30,
    email: 'alice@example.com'
  };
  console.log('User object:', user);

  // Table display
  const users = [
    { name: 'Alice', age: 30, role: 'Admin' },
    { name: 'Bob', age: 25, role: 'User' },
    { name: 'Charlie', age: 35, role: 'Editor' }
  ];
  console.table(users);

  // Grouped logs
  console.group('User Details');
  console.log('Name:', user.name);
  console.log('Age:', user.age);
  console.log('Email:', user.email);
  console.groupEnd();

  // Assertions
  console.assert(user.age >= 18, 'User should be 18 or older');
  console.assert(user.age < 18, 'This will fail and show message');

  // Stack trace
  console.trace('Execution path trace');

  const output = document.getElementById('consoleInfo');
  output.className = 'success';
  output.textContent = 'โœ“ Console examples executed! Check the Developer Console (F12) to see the output.';
});

// Example 2: Performance Timing
document.getElementById('timingBtn').addEventListener('click', function() {
  const output = document.getElementById('timingOutput');
  output.textContent = 'Measuring performance...';

  // Slow operation (loop)
  console.time('Slow Loop');
  let sum = 0;
  for (let i = 0; i < 1000000; i++) {
    sum += i;
  }
  console.timeEnd('Slow Loop');

  // Fast operation (direct calculation)
  console.time('Fast Calculation');
  const fastSum = (999999 * 1000000) / 2;
  console.timeEnd('Fast Calculation');

  output.className = 'success';
  output.innerHTML = 'โœ“ Performance tests completed!<br><br>' +
    'Check console for timing results.<br><br>' +
    '<strong>Slow loop result:</strong> ' + sum + '<br>' +
    '<strong>Fast calculation result:</strong> ' + fastSum + '<br><br>' +
    'Notice the time difference in console!';
});

// Example 3: Buggy vs Fixed Code
document.getElementById('buggyBtn').addEventListener('click', function() {
  const output = document.getElementById('bugOutput');

  try {
    console.log('=== Running Buggy Code ===');

    // Intentional bug: trying to access property of undefined
    const user = null;
    const name = user.name; // This will throw an error

    output.className = 'success';
    output.textContent = 'User name: ' + name;
  } catch (error) {
    console.error('โŒ Bug caught:', error.message);
    console.log('Stack trace:', error.stack);

    output.className = 'error';
    output.innerHTML = '<strong>โœ— Error Occurred!</strong><br><br>' +
      '<strong>Message:</strong> ' + error.message + '<br><br>' +
      '<strong>How to debug:</strong><br>' +
      '1. Check browser console for error details<br>' +
      '2. Look at the line number in error message<br>' +
      '3. Use console.log to check variable values<br>' +
      '4. Set breakpoints in browser DevTools';
  }
});

document.getElementById('fixedBtn').addEventListener('click', function() {
  const output = document.getElementById('bugOutput');

  try {
    console.log('=== Running Fixed Code ===');

    const user = null;

    // Fixed: Check if user exists before accessing properties
    if (user && user.name) {
      console.log('โœ“ User name:', user.name);
      output.textContent = 'User name: ' + user.name;
    } else {
      console.warn('โš ๏ธ User is null or has no name');
      output.className = 'success';
      output.innerHTML = '<strong>โœ“ Code Fixed!</strong><br><br>' +
        'User is null, but code handled it gracefully.<br><br>' +
        '<strong>Fix applied:</strong> Added null check before accessing properties';
    }
  } catch (error) {
    console.error('Error:', error);
    output.className = 'error';
    output.textContent = 'Error: ' + error.message;
  }
});
Notes
  • Use DevTools: Learn your browser's Developer Tools (F12) - they're your most powerful debugging weapon.
  • console.log Strategically: Place logs before/after problem areas to narrow down where errors occur.
  • Remove Debug Code: Don't ship console.log statements to production - remove or use proper logging libraries.