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
- Open DevTools (F12 or Cmd+Option+I)
- Go to "Sources" tab
- Find your file in the file tree
- Click on a line number to add a breakpoint
- Reload the page or trigger the code
- 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