Basic Console Methods
- Use
console.log()
, info()
, warn()
, and error()
to track messages and warnings.
- Organize logs with
group()
and time actions with time()
and timeEnd()
.
- Display data cleanly using
console.table()
.
console.log('Debug message');
console.group('User Ops');
console.log('Creating...');
console.groupEnd();
console.table([{ name: 'John' }, { name: 'Jane' }]);
console.time('fetchData');
console.timeEnd('fetchData');
Advanced Console Techniques
- Trace execution with
console.trace()
.
- Add logic to logs or style them for emphasis.
- Count actions with
count()
and reset them with countReset()
.
console.assert(user.age >= 18, 'User must be 18');
console.trace('Where is this called from?');
console.count('API call');
Debugging Objects and Arrays
- Use
console.dir()
for deep object views.
- Spread arrays for full content visibility.
- Log object keys, values, and entries clearly.
console.dir(user, { depth: null });
console.log([...array]);
console.log(Object.entries(user));
Try-Catch Blocks
- Catch errors and handle fallback logic.
- Always log
error.message
and error.stack
for context.
- In async functions, use try/catch with
await
.
try {
const result = risky();
} catch (error) {
console.error(error.message);
}
Custom Error Classes
- Create your own
Error
types like ValidationError
or NetworkError
.
- Helps categorize and respond to different failure types.
class ValidationError extends Error {
constructor(msg, field) {
super(msg);
this.field = field;
}
}
Global Error Handling
- Catch uncaught errors in the browser or Node.js globally.
- Use
window.addEventListener('error')
and unhandledrejection
.
window.addEventListener('error', event => {
console.error('Global error:', event.message);
});
Source Maps
- Enable source maps to trace back to original source files.
- Use with Babel or Webpack for better error visibility in minified code.
devtool: 'source-map'
Debugger Statement
- Use
debugger
to pause code in DevTools when a condition is met.
- Especially useful for inspecting variables at specific logic points.
if (user.age < 18) debugger;
Network Debugging
- Wrap
fetch
and XHR to log requests and responses.
- Monitor network resource loading with
PerformanceObserver
.
window.fetch = (...args) => {
console.log('Fetch:', args);
return originalFetch(...args);
};
Undefined and Null Issues
- Use optional chaining (
?.
) and nullish coalescing (??
) to handle safely.
- Log types and check for null/undefined clearly.
const age = user?.profile?.age ?? 0;
console.log(typeof value);
Async/Await Debugging
- Use logs before/after each
await
to trace flow.
- Wrap the whole sequence in
try/catch
to isolate failures.
try {
const result = await step();
console.log('Done:', result);
} catch (e) {
console.error(e);
}
DOM Debugging
- Check if DOM elements exist before interacting.
- Use
MutationObserver
to track DOM changes.
- Inspect event listeners with tools like
getEventListeners()
.
const el = document.getElementById('myElement');
if (!el) console.error('Not found');
Memory Leak Detection
- Use
performance.memory
to inspect memory usage (Chrome only).
- Watch for event listeners that aren’t removed.
if ('memory' in performance) {
console.log(performance.memory.usedJSHeapSize);
}
Debug Helper Functions
- Build centralized helpers for dev-only logging, timing, and error formatting.
const debug = {
log: (label, data) => console.log(`${label}:`, data),
error: (label, err) => console.error(`${label}:`, err),
};
Environment Detection
- Add conditional logging based on
NODE_ENV
.
- Avoid debug logs in production automatically.
const isDev = process.env.NODE_ENV === 'development';
if (isDev) console.log('Only in dev!');