Bugs are inevitable, so knowing how to find and fix them is as important as knowing how to write code. This lesson covers the browser DevTools toolkit: structured console logging with log/warn/error/table, pausing execution with the debugger statement and manual breakpoints, reading the Scope and Call Stack panels, and diagnosing failed network requests.
1JS Debugging | JavaScript Tutorial - In-Depth Guide Part 1
Bugs are inevitable. Debugging is the skill of finding and fixing them. Let's master the tools that make your code transparent.
// The Debugger's ToolkitDebugging Toolkit
2JS Debugging | JavaScript Tutorial - In-Depth Guide Part 2
Level 1: The Console. Use console.log() to track variables, but don't forget .warn() and .error() for better visibility.
console.log('Status: OK');
console.warn('Low Memory!');
console.error('Critical Failure!');Console Levels
3JS Debugging | JavaScript Tutorial - In-Depth Guide Part 3
For objects and arrays, console.table() is a game-changer. It formats data into a readable grid.
const users = [{id: 1, name: 'Ada'}, {id: 2, name: 'Bob'}];
console.table(users);Console Table
4JS Debugging | JavaScript Tutorial - In-Depth Guide Part 4
Level 2: Freezing Time. The 'debugger' keyword pauses execution completely if your DevTools are open.
function calculate(n) {
const result = n * 2;
debugger; // Execution stops here!
return result;
}Breakpoints
5JS Debugging | JavaScript Tutorial - In-Depth Guide Part 5
While paused, you can inspect the 'Scope' panel to see the exact values of every variable in that moment.
// Paused at line 3
// result = 10
// n = 5Scope Inspection
6JS Debugging | JavaScript Tutorial - In-Depth Guide Part 6
The Call Stack: This panel shows you the trail of functions that led to the current line. Essential for tracing bugs.
function start() { step1(); }
function step1() { step2(); }
function step2() { debugger; }Call Stack
7JS Debugging | JavaScript Tutorial - In-Depth Guide Part 7
Network Tab: If your 'fetch' is failing, check the Network tab to see the exact request and response headers.
<h1>Tab: Network</h1>Network Inspection
8JS Debugging | JavaScript Tutorial - In-Depth Guide Part 8
Debugging mastery unlocked! You now have the x-ray vision needed to build perfect code.
<h1>Status: Bug-Free</h1>Status: Bug-Free
9JS Debugging | JavaScript Tutorial - In-Depth Guide Part 9
You have completed the core JavaScript curriculum! Ready for the final exam?
<h1>JS: 100% COMPLETE</h1>On to Final Exam
10Step-by-Step Breakdown
Bugs are inevitable. Debugging is the skill of finding and fixing them. Let's master the tools that make your code transparent.
Level 1: The Console. Use console.log() to track variables, but don't forget .warn() and .error() for better visibility.
For objects and arrays, console.table() is a game-changer. It formats data into a readable grid.
Checkpoint: Which console method is best for visualizing an array of objects as a grid?
- āconsole.log()
- āconsole.table()
Level 2: Freezing Time. The 'debugger' keyword pauses execution completely if your DevTools are open.
While paused, you can inspect the 'Scope' panel to see the exact values of every variable in that moment.
Checkpoint: Do you need to modify your source code to add a breakpoint in the browser?
- āYes, you must type 'debugger'
- āNo, you can click line numbers in DevTools
The Call Stack: This panel shows you the trail of functions that led to the current line. Essential for tracing bugs.
Network Tab: If your 'fetch' is failing, check the Network tab to see the exact request and response headers.
Checkpoint: What happens to the 'debugger' statement if DevTools is CLOSED?
- āThe browser crashes
- āIt is ignored and code runs normally
Debugging mastery unlocked! You now have the x-ray vision needed to build perfect code.
You have completed the core JavaScript curriculum! Ready for the final exam?
Level Up š
Advanced cheat sheets, SEO tricks, and interview prep for this topic.
Browser Support
Fully supported.
Fully supported.
Fully supported.
Fully supported.
Accessibility (A11y)
1DevTools Can Simulate Vision Deficiencies to Test Your UI
Chrome's Rendering tab (More Tools > Rendering > Emulate vision deficiencies) lets you preview your page as it would appear to users with protanopia, deuteranopia, or blurred vision ā use it as part of your debugging routine to catch color-contrast and color-only-signal problems before shipping.
// DevTools > More Tools > Rendering > Emulate vision deficienciesSEO Implications
- 1
Console Errors Can Signal Broken Functionality That Crawlers Also Experience
If your Console tab is full of uncaught errors on page load, a search engine's rendering crawler executing that same JavaScript may fail at the same point, potentially indexing a broken or incomplete version of the page. Treat a clean console as part of your technical SEO checklist, not just a developer nicety.
Best Practices
Prefer console.table() Over console.log() for Arrays of Objects
Logging an array of objects with console.log() forces you to expand each entry one at a time to compare values. console.table() lays every object out as rows and columns automatically, making it far faster to spot the one row with a wrong value.
Use Conditional Breakpoints Instead of Wrapping debugger; in an if Statement
Right-clicking a line number in the Sources panel lets you add a breakpoint that only triggers when a condition you specify is true (e.g. `i === 47`), achieving the same targeted pause as a manual `if (i === 47) { debugger; }` without adding debugging code to your actual source file.
Frequent Bugs
A fetch() call appears to silently fail with no visible error in the console.
fetch() only rejects on network failures ā an HTTP error response like a 404 or 500 still resolves successfully, so the failure is easy to miss unless you explicitly check `response.ok` or `response.status`. Open the Network tab to see the actual status code and response body for the failed request.
Real-World Examples
Tracing a Bug Through the Call Stack
A button's onClick handler was throwing 'Cannot read properties of undefined', but the error didn't make it obvious which of several nested function calls actually passed in the bad data.
function handleClick() { processOrder(order); }
function processOrder(order) { validateItems(order.items); }
function validateItems(items) {
debugger; // Inspect the Call Stack panel here to see the full path: handleClick -> processOrder -> validateItems
return items.every(i => i.price > 0);
}