VS Vikesh Singh

Courses JavaScript Lesson 17

JAVASCRIPT · LESSON 17 OF 18

Debugging JavaScript: Console Tricks That Save Hours

· 4 min read

By now you've written enough JavaScript to have hit bugs — code that doesn't do what you expected, or throws an error you don't immediately understand. T

By now you've written enough JavaScript to have hit bugs — code that doesn't do what you expected, or throws an error you don't immediately understand. This lesson is about the console and developer tools properly, so debugging stops being guesswork and becomes a fast, repeatable process.

Beyond Console.log

You've used console.log throughout this course already, but it has more range than just printing a single value.

const user = { name: "Tony Stark", alias: "Iron Man" };
const numbers = [1, 2, 3];

console.log("User:", user, "Numbers:", numbers);
console.table([
  { name: "Tony Stark", role: "admin" },
  { name: "Vikesh Singh", role: "editor" }
]);
console.warn("This is a warning");
console.error("This is an error message");

console.log can take multiple comma-separated arguments and prints them all on one line, which beats concatenating everything into one string manually. console.table is genuinely excellent for arrays of objects — it renders an actual readable table in the console, with each object's keys as columns, far easier to scan than a wall of nested braces. console.warn and console.error print with distinct styling (yellow and red, typically) and get automatically picked up by error-tracking and filtering tools, which matters more once you're working on a real project with a noisy console.

Reading Error Messages

Reading an actual error message properly is a skill in itself. Take this one apart:

const data = null;
console.log(data.name);

This throws: "Uncaught TypeError: Cannot read properties of null (reading 'name')". Break it down: TypeError tells you the category (you tried to use a value in a way its type doesn't support); "Cannot read properties of null" tells you the actual value was null; "(reading 'name')" tells you exactly which property access failed. Beginners often see "error" and panic, but this specific message is actually telling you precisely what to fix: data is null when you expected it to be an object with a name property — the same null-handling issue from the DOM and localStorage lessons shows up constantly in real debugging.

Using The Elements And Network Tabs

The browser's developer tools (F12, or right-click → Inspect) give you far more than the console tab. The Elements tab shows the live DOM — genuinely live, meaning you can watch it change in real time as your JavaScript runs, which is invaluable for confirming whether your DOM-manipulation code (lesson 7) actually did what you expected. The Network tab shows every fetch request your page makes (lesson 13), including the exact response body, status code, and timing — essential for debugging API calls, especially a request that silently failed because of a wrong URL or a CORS issue.

Debugging With Breakpoints

Breakpoints are the single most powerful debugging tool, and most beginners skip them in favor of scattering console.log everywhere. A breakpoint pauses your code mid-execution at a specific line, letting you inspect every variable's current value at that exact moment.

function calculateTotal(items) {
  let total = 0;
  for (const item of items) {
    total += item.price;
  }
  return total;
}

Clicking the line number for total += item.price in the Sources tab of DevTools sets a breakpoint there. When calculateTotal runs, execution pauses right before that line, and you can hover over item, total, or any other visible variable to see their exact current values, then step forward one line at a time. This is dramatically faster than guessing where to place console.log statements, removing them, and reloading the page over and over.

The Debugger Statement

A genuinely useful shortcut for quick inspection without a full breakpoint: the debugger statement, placed directly in your code.

function processOrder(order) {
  debugger;
  const total = order.items.reduce((sum, i) => sum + i.price, 0);
  return total;
}

If DevTools is open when this line runs, execution pauses automatically, exactly like a manually placed breakpoint — handy for pausing at a specific spot without having to find the right line number in the Sources tab first. Just remember to remove debugger statements before considering your code finished, since they'll pause execution for anyone with DevTools open.

A practical tip that saves real time: when you hit a confusing bug, resist the urge to immediately start changing code. First reproduce it reliably, then add one console.log (or breakpoint) right before the point where things go wrong, confirm your assumption about what the value should be, and only then make a change. Changing code before you understand the actual problem tends to create new bugs on top of the original one.

A final practical habit: keep your console reasonably clean as your project grows, removing stray console.log statements once you've confirmed the thing you were checking actually works. A console cluttered with old debug output makes it harder to spot a genuinely new warning or error when one shows up later, which defeats much of the purpose of having a clean, readable console in the first place.

Worth trying right now: take any function you've written in this course, intentionally introduce a bug (like a typo in a variable name, or an off-by-one in a loop condition), then use a breakpoint in DevTools, rather than console.log, to find and understand it. Getting comfortable pausing execution rather than just printing values is the biggest single upgrade to your debugging speed.