Debugging and Error Prevention
Techniques for debugging JavaScript applications
Challenge
Section titled “Challenge”Quickly identify and fix bugs in production and development environments. Use debugging tools and strategies effectively.
Explanation
Section titled “Explanation”Debugging is an essential skill. Understanding browser dev tools and debugging patterns helps identify issues quickly.
Console Methods
Section titled “Console Methods”// Loggingconsole.log('Basic log');console.warn('Warning');console.error('Error');console.info('Info');
// Groupingconsole.group('API Calls');console.log('GET /users');console.log('GET /posts');console.groupEnd();
// Tablesconst users = [ { name: 'John', age: 30 }, { name: 'Jane', age: 25 }];console.table(users);
// Timingconsole.time('fetch');// ... code ...console.timeEnd('fetch'); // Logs: fetch: 234.5ms
// Assertionsconsole.assert(value > 0, 'Value must be positive');Breakpoints and Debugging
Section titled “Breakpoints and Debugging”// Debugger statement (pauses execution)function problematicFunction() { debugger; // Execution pauses here in dev tools return complexCalculation();}
// Conditional breakpoints (dev tools only)// Right-click line number -> Add conditional breakpointif (userId === 123) { debugger; // Only breaks for specific user}Stack Traces
Section titled “Stack Traces”function outer() { inner();}
function inner() { deepest();}
function deepest() { console.trace('Stack trace'); // Shows full call stack throw new Error('Something went wrong');}
outer();/* Stack trace: at deepest (file.js:10) at inner (file.js:6) at outer (file.js:3) at <anonymous> (file.js:14)*/Error Handling Strategies
Section titled “Error Handling Strategies”// Try-catch for synchronous errorstry { JSON.parse('{invalid}');} catch (e) { console.error('Parse error:', e.message);} finally { console.log('Cleanup'); // Always runs}
// Distinguish error typestry { someOperation();} catch (error) { if (error instanceof TypeError) { console.error('Type error:', error); } else if (error instanceof SyntaxError) { console.error('Syntax error:', error); } else { console.error('Unknown error:', error); }}
// Async error handlingasync function fetchData(url) { try { const response = await fetch(url); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } return await response.json(); } catch (error) { console.error('Fetch failed:', error); // Fallback or recovery return null; }}Source Maps
Section titled “Source Maps”// In build config (webpack, vite, etc)// Enable source maps for production debugging
// .map files allow browser to show original source code// even when using minified/transpiled code
// In dev tools:// Sources tab shows original files instead of bundled codeMemory Leaks Detection
Section titled “Memory Leaks Detection”// Common memory leak: Event listenersconst element = document.getElementById('button');
// ❌ Bad: Never removedelement.addEventListener('click', () => console.log('clicked'));
// ✅ Good: Remove when doneconst handler = () => console.log('clicked');element.addEventListener('click', handler);// Later...element.removeEventListener('click', handler);
// ❌ Bad: Circular referencesclass Node { constructor(value) { this.value = value; this.parent = null; }}
// ✅ Good: Use WeakMap to avoid memory leaksconst parentMap = new WeakMap();const node = new Node(5);parentMap.set(node, parentNode);Performance Profiling
Section titled “Performance Profiling”// Performance APIperformance.mark('operation-start');// ... code ...performance.mark('operation-end');
performance.measure( 'operation', 'operation-start', 'operation-end');
const measure = performance.getEntriesByName('operation')[0];console.log(`Operation took ${measure.duration}ms`);
// Entry observationsconst observer = new PerformanceObserver((list) => { for (const entry of list.getEntries()) { console.log(`${entry.name}: ${entry.duration}ms`); }});
observer.observe({ entryTypes: ['measure', 'navigation'] });Best Practices
Section titled “Best Practices”// Use descriptive error messages// ❌ throw new Error('Error');// ✅ throw new Error('Failed to fetch user data from API');
// Include context in logs// ❌ console.log(error);// ✅ console.error('Failed to parse config:', { error, file: 'config.json' });
// Use custom error classesclass ValidationError extends Error { constructor(field, value) { super(`Validation failed for ${field}: ${value}`); this.name = 'ValidationError'; this.field = field; }}
try { throw new ValidationError('email', 'invalid');} catch (error) { if (error instanceof ValidationError) { console.log('Field:', error.field); }}