Lesson 11 / 11

Error Handling and Debugging Like a Pro

try/catch with real error info

try {
  const data = JSON.parse(userInput);
} catch (error) {
  console.error("Invalid JSON:", error.message);
}

Wrap any code that might realistically fail — parsing user input, calling an external API, accessing a property on a value that might be null — in try/catch rather than letting the error crash your whole script.

Custom error types

class ValidationError extends Error {
  constructor(message) {
    super(message);
    this.name = "ValidationError";
  }
}

function checkAge(age) {
  if (age < 0) throw new ValidationError("Age cannot be negative");
  return age;
}

try {
  checkAge(-5);
} catch (error) {
  if (error instanceof ValidationError) {
    console.log("Please enter a valid age.");
  } else {
    throw error;   // re-throw anything you didn't expect
  }
}

Creating your own error class by extending the built-in Error lets you distinguish between different failure types in a catch block, rather than treating every error identically. Re-throwing errors you don’t recognize is good practice — silently swallowing unexpected errors makes bugs far harder to track down later.

Debugging tools worth knowing

  • console.table(data) — renders an array of objects as a readable, sortable table right in DevTools
  • console.error(x) / console.warn(x) — visually distinct from console.log, and easy to filter for in DevTools
  • debugger; — pauses execution right at that line when DevTools is open, letting you inspect every variable’s current value
  • Breakpoints in the browser’s Sources panel — click a line number to pause there and step through code one line at a time

You’ve completed the course

From your first console.log to closures, classes, and professional error handling — you now have a solid, professional-level JavaScript foundation. Take the certification assessment next, or apply to the Frontend Development Internship to build something real.