Debugging Techniques

Find and fix bugs faster. DevTools, breakpoints, and systematic strategies.

Console Methods

Beyond console.log — powerful inspection tools.

// Basics:
console.log("value:", x);     // general output
console.error("Failed!");     // red, shows stack trace
console.warn("Deprecated");   // yellow warning
console.info("FYI");          // informational

// Structured data:
console.table([
  { name: "Alice", age: 25 },
  { name: "Bob", age: 30 },
]); // beautiful table view!

console.dir(document.body, { depth: 2 }); // object tree
console.group("Network");
  console.log("Request sent");
  console.log("Response received");
console.groupEnd();

// Timing:
console.time("fetch");
await fetch("/api/data");
console.timeEnd("fetch"); // "fetch: 142ms"

// Counting:
function process(item) {
  console.count("processed"); // "processed: 1", "processed: 2"...
}

// Conditional:
console.assert(x > 0, "x must be positive!", { x });
// Only logs if assertion FAILS

// Stack trace:
console.trace("How did we get here?"); // prints call stack

Breakpoints

Pause execution and inspect state at any point.

// The 'debugger' statement — programmatic breakpoint:
function processData(data) {
  debugger; // execution pauses here when DevTools is open
  const result = transform(data);
  return result;
}

// Types of breakpoints in DevTools:
// 1. Line breakpoints — click the line number
// 2. Conditional — right-click line → "Add conditional"
//    Only pause when: items.length > 100
// 3. DOM breakpoints — pause when DOM changes
//    Right-click element → "Break on" → subtree/attribute/removal
// 4. XHR/Fetch breakpoints — pause on network requests
//    Sources → XHR Breakpoints → add URL pattern
// 5. Event listener breakpoints
//    Sources → Event Listener Breakpoints → check "click"
// 6. Exception breakpoints
//    Sources → ⏸ icon → "Pause on caught exceptions"
// When paused at a breakpoint, you can:
// • Hover variables to see their value
// • Use the Scope panel to see all variables
// • Use the Watch panel for expressions
// • Use the Console to evaluate code in current scope

// Stepping controls:
// F8  — Resume (continue to next breakpoint)
// F10 — Step Over (execute line, don't enter functions)
// F11 — Step Into (enter the function call)
// Shift+F11 — Step Out (finish current function)

// Pro tip: Logpoints (no code changes needed):
// Right-click line → "Add logpoint"
// Enter: "x is:", x, "items:", items.length
// It logs without pausing — like console.log but no code change!

DevTools

Chrome DevTools panels for debugging JavaScript.

// Sources Panel — the main debugger:
// • See all loaded files
// • Set breakpoints
// • Step through code
// • Edit files (Workspaces)
// • Snippets for quick scripts

// Network Panel — inspect requests:
// • See all HTTP requests/responses
// • Check timing (DNS, connect, TTFB)
// • Filter by type (XHR, JS, CSS)
// • Throttle speed (Slow 3G, Offline)
// • Block requests to test failures

// Performance Panel — find bottlenecks:
// • Record page activity
// • See flame chart (what took time)
// • Identify long tasks (>50ms)
// • Find layout thrashing
// • Measure FPS and jank

Sources for code debugging, Network for HTTP inspection, Performance for bottleneck analysis.

1 / 2

Strategies

Systematic approaches to finding bugs.

// 1. Reproduce Reliably:
// Can you make the bug happen consistently?
// What are the exact steps?
// Does it happen in all browsers? All screen sizes?

// 2. Isolate the Problem (Binary Search):
// Comment out half the code — does bug persist?
// If yes → bug is in the remaining half
// If no → bug was in the commented half
// Repeat until you find the exact line

// 3. Check Assumptions:
console.log(typeof value);     // is it the type you expect?
console.log(JSON.stringify(obj)); // is the shape correct?
console.log(arr.length);       // is it populated?

// 4. Rubber Duck Debugging:
// Explain the code LINE BY LINE to someone (or a rubber duck)
// "This line should give me an array of users..."
// "Wait — it's returning a Promise, not the actual array!"

// 5. Git Bisect (find which commit broke it):
// git bisect start
// git bisect bad  (current is broken)
// git bisect good abc123 (this commit was fine)
// Git binary-searches commits for you

Common Bugs

Frequent JavaScript mistakes and how to spot them.

// 1. Off-by-one errors:
for (let i = 0; i <= arr.length; i++) // ❌ <= should be <
arr.slice(0, 3); // returns indices 0,1,2 (not 3!)

// 2. Async timing:
let data;
fetch("/api").then(res => { data = res.json(); });
console.log(data); // undefined! (fetch hasn't resolved)

// 3. Reference vs value:
const original = [1, 2, 3];
const copy = original; // same reference!
copy.push(4);
original.length; // 4 (oops!)

// 4. this context:
const obj = {
  name: "Alice",
  greet: () => this.name, // ❌ arrow function has no 'this'
};

// 5. Equality gotchas:
0 == "";     // true (type coercion)
null == undefined; // true
NaN === NaN; // false!

// 6. Closure in loops:
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i)); // 3, 3, 3 (use let!)
}

// 7. Missing await:
async function load() {
  const data = fetch("/api"); // ❌ missing await → Promise object!
  return data.json(); // ❌ data.json is not a function
}

FAQ

Common questions about debugging.