Error handling and debugging techniques in JavaScript
// Basic try-catch
try {
const result = riskyOperation();
console.log('Success:', result);
} catch (error) {
console.error('Error occurred:', error.message);
}
// Try-catch-finally
try {
performOperation();
} catch (error) {
console.error('Error:', error);
} finally {
cleanup(); // Always runs
}
// Throwing errors
function divide(a, b) {
if (b === 0) {
throw new Error('Division by zero!');
}
return a / b;
}
try {
console.log(divide(10, 0));
} catch (error) {
console.error(error.message);
}
// Custom error types
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateUser(user) {
if (!user.email) {
throw new ValidationError('Email is required');
}
}
try {
validateUser({ name: 'Alice' });
} catch (error) {
if (error instanceof ValidationError) {
console.error('Validation failed:', error.message);
}
}
// Console methods
console.log('Regular log');
console.info('Information');
console.warn('Warning!');
console.error('Error!');
const users = [
{ id: 1, name: 'Alice', age: 25 },
{ id: 2, name: 'Bob', age: 30 }
];
console.table(users);
// Console timing
console.time('operation');
for (let i = 0; i < 1000000; i++) {}
console.timeEnd('operation');
// Console trace
function level1() { level2(); }
function level2() { level3(); }
function level3() { console.trace('Call stack'); }
level1();
// Debugger statement
function complexFunction(data) {
debugger; // Pauses in DevTools
return processData(data);
}
// Global error handler
window.addEventListener('error', (event) => {
console.error('Global error:', event.error);
console.error('File:', event.filename);
console.error('Line:', event.lineno);
});
// Unhandled promise rejections
window.addEventListener('unhandledrejection', (event) => {
console.error('Unhandled rejection:', event.reason);
});
// Defensive programming
function safeAccess(obj, path, defaultValue = null) {
return path.split('.').reduce((current, key) => {
return current?.[key];
}, obj) ?? defaultValue;
}
const user = { profile: { name: 'Alice' } };
console.log(safeAccess(user, 'profile.name')); // 'Alice'
console.log(safeAccess(user, 'profile.age', 0)); // 0
JavaScript error handling uses try...catch...finally blocks to manage exceptions gracefully. I throw custom errors with throw new Error('message') for better debugging. The finally block runs regardless of success or failure. Using console.error(), console.warn(), and console.log() provides different severity levels. The console.table() displays arrays and objects in table format. Debugger statements pause execution for inspection with debugger; keyword. Browser DevTools breakpoints allow stepping through code. The console.trace() shows call stack. Stack traces help identify error origins. Understanding error types (TypeError, ReferenceError, SyntaxError) aids debugging. I use source maps for debugging minified code. Error boundaries catch React component errors.