TechLead

Debugging

Console, breakpoints, devtools

Debugging JavaScript

Debugging is the process of finding and fixing errors in your code. Modern browsers have powerful developer tools that make debugging easier.

Console Methods

// Basic logging
console.log('Hello');           // General output
console.info('Info message');   // Informational
console.warn('Warning!');       // Warning (yellow)
console.error('Error!');        // Error (red)

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

// Template literals for formatting
const user = 'Bob';
console.log(`Welcome, ${user}!`);

// Log with label (cleaner output)
console.log({ user, count: 5, active: true });

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

Advanced Console

// Group related logs
console.group('User Details');
console.log('Name: Alice');
console.log('Age: 30');
console.groupEnd();

// Measure execution time
console.time('Operation');
// ... some code ...
console.timeEnd('Operation');  // Logs: "Operation: 123.45ms"

// Count function calls
function myFunction() {
  console.count('myFunction called');
}
myFunction();  // "myFunction called: 1"
myFunction();  // "myFunction called: 2"

// Stack trace
console.trace('Trace point');

// Conditional logging
const x = 5;
console.assert(x > 10, 'x should be greater than 10');

Using Breakpoints

Setting Breakpoints in DevTools

  1. Open DevTools (F12 or Cmd+Option+I)
  2. Go to "Sources" tab
  3. Find your file in the file tree
  4. Click on a line number to add a breakpoint
  5. Reload the page or trigger the code
  6. Execution will pause at the breakpoint
// Debugger statement (programmatic breakpoint)
function calculate(a, b) {
  debugger;  // Execution pauses here if DevTools is open
  return a + b;
}

Step Through Code

When paused at a breakpoint, you can:

▶️ Resume (F8)

Continue execution until next breakpoint

↘️ Step Over (F10)

Execute current line and move to next

⤵️ Step Into (F11)

Go inside function call

⤴️ Step Out (Shift+F11)

Finish current function and return

Inspecting Variables

function processUser(user) {
  debugger;  // Pause here
  
  // When paused, you can:
  // 1. Hover over variables to see values
  // 2. Type in console: user, user.name, etc.
  // 3. Check "Scope" panel in DevTools
  // 4. Add watches for expressions
  
  const name = user.name.toUpperCase();
  return name;
}

Common Errors & Solutions

TypeError: Cannot read property 'x' of undefined

// Problem
const user = null;
console.log(user.name);  // Error!

// Solutions
if (user) {
  console.log(user.name);
}

// Or use optional chaining
console.log(user?.name);  // undefined (no error)

ReferenceError: variable is not defined

// Problem
console.log(myVar);  // Error! Variable doesn't exist

// Solution: Check spelling and declaration
const myVar = 'Hello';
console.log(myVar);  // "Hello"

SyntaxError: Unexpected token

// Problem: Missing closing bracket/parenthesis
function test() {
  console.log('hi');
// Missing closing brace!

// Solution: Check all brackets are closed
function test() {
  console.log('hi');
}  // Added closing brace

Network Debugging

// Check Network tab in DevTools to debug:

// 1. API request status
fetch('https://api.example.com/users')
  .then(response => {
    console.log('Status:', response.status);  // 200, 404, 500, etc.
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .catch(error => console.error('Fetch error:', error));

// 2. Inspect request/response headers
// 3. Check payload data
// 4. View response time

Performance Profiling

// Measure function performance
function slowFunction() {
  console.time('slowFunction');
  
  // Your code here
  for (let i = 0; i < 1000000; i++) {
    // ...
  }
  
  console.timeEnd('slowFunction');  // "slowFunction: 45.2ms"
}

// Use Performance tab in DevTools:
// 1. Click record button
// 2. Perform actions
// 3. Stop recording
// 4. Analyze flame graph for bottlenecks

Memory Leaks

// Common memory leak: Event listeners not removed
const button = document.querySelector('#btn');
const handler = () => console.log('Clicked');

// Add listener
button.addEventListener('click', handler);

// Later, if you remove button from DOM:
button.remove();

// But listener still exists in memory!
// Fix: Remove listener before removing element
button.removeEventListener('click', handler);
button.remove();

// Use Memory tab in DevTools to detect leaks:
// 1. Take heap snapshot
// 2. Perform actions
// 3. Take another snapshot
// 4. Compare to see what's growing

🛠️ DevTools Shortcuts

  • F12 / Cmd+Opt+I: Open DevTools
  • Cmd+Opt+J: Open Console directly
  • Cmd+P: Quick file search
  • Cmd+Shift+P: Command palette
  • Cmd+F: Search in current file

✓ Debugging Best Practices

  • • Use console.log() strategically, not everywhere
  • • Remove debug logs before committing code
  • • Use breakpoints over console.log for complex debugging
  • • Check Network tab for API issues
  • • Read error messages carefully—they tell you what's wrong!
  • • Use descriptive variable names to reduce confusion
  • • Test small pieces of code in isolation