JavaScript: JavaScript Errors and Debugging
Last updated: 2026-10-13
Writing bug-free code is impossible — even the creator of JavaScript produced the typeof null === "object" bug in just 10 days. So learning to find bugs and handle errors is even more important than learning to write code.
1. Error Handling and Debugging
(1) Common Error Types
| Error Type | Cause | Example |
|---|---|---|
SyntaxError |
Invalid syntax | if (true { — mismatched parentheses |
ReferenceError |
Accessing a non-existent variable | console.log(notExist) |
TypeError |
Operating on the wrong type | undefined.toString() |
RangeError |
Value out of valid range | new Array(-1) |
SyntaxError is caught before code execution (parsing phase). The other three are runtime errors.
(2) try...catch...finally
Use try...catch to catch runtime errors and prevent your program from crashing:
<script>
try {
const data = JSON.parse('{bad json}');
} catch (error) {
console.log("Parse failed:", error.message);
} finally {
console.log("Cleanup work");
}
</script>
The error object in catch has two commonly used properties:
error.message— a description of the errorerror.name— the error type name
(3) throw — Manually Throwing Errors
try...catch can only catch runtime errors, but business logic errors need to be thrown manually:
<script>
function setAge(age) {
if (typeof age !== "number" || age < 0) {
throw new Error("Age must be a positive number");
}
console.log("Age set to: " + age);
}
try {
setAge(-5);
} catch (e) {
console.log(e.message);
}
</script>
throw can throw any value, but using new Error() or its subclasses is recommended — they include stack trace information.
(4) Custom Error Messages
Use subclasses of Error or custom properties to provide richer error information:
<script>
class ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
try {
throw new ValidationError("email", "Invalid email format");
} catch (e) {
console.log(e.name + " [" + e.field + "]: " + e.message);
}
</script>
(5) Browser DevTools (F12)
| Panel | Purpose |
|---|---|
| Console | View logs, execute code, see errors |
| Sources | Set breakpoints, step through code, inspect variables |
| Network | Inspect network requests, response status, load times |
| Elements | View/modify DOM and styles |
Breakpoint debugging is the most powerful debugging technique: click a line number in the Sources panel to set a breakpoint, refresh the page, and the code pauses at that point — step through line by line, inspect variables, and examine the call stack.
(6) The console Family
| Method | Purpose |
|---|---|
console.log() |
General output |
console.warn() |
Warning (yellow) |
console.error() |
Error (red) |
console.table() |
Display arrays/objects as a table |
console.time() / console.timeEnd() |
Timing |
console.group() / console.groupEnd() |
Grouped output |
console.clear() |
Clear the console |
console.table is especially useful for displaying arrays of objects — far more readable than log.
(7) Debugging Tips
- Comment out halves: Comment out half the code, see which half has the problem, and narrow it down step by step
- console.log everywhere: Print variable values at key points — primitive but effective
- Breakpoint debugging: More powerful than
console.log— pause execution and modify variables in real time - Rubber duck debugging: Explain your code line by line to a rubber duck (or a colleague). Often, you'll find the bug halfway through your explanation.
▶ Example: try/catch for JSON Parsing
▶ Try it Yourself▶ Example: Custom Errors and Form Validation
▶ Try it Yourself▶ Example: Error Types Quick Reference and console Methods
▶ Try it Yourself❓ FAQ
SyntaxError is thrown during the parsing phase before execution even begins, so the try block is never reached. However, if a SyntaxError occurs at runtime (e.g. JSON.parse fails, or new Function("bad syntax")), it can be caught.catch alone is sufficient.return is for normal flow — the caller handles the returned value. throw is for abnormal flow — it skips subsequent code and walks up the call stack looking for a catch. Use throw for errors, return for normal results.📖 Summary
try/catchcatches runtime errors;finallyalways runs, perfect for cleanupthrowraises errors manually — preferthrow new Error("message")over strings or numbers- Error objects have
nameandmessageproperties; the browser console shows the full stack trace - DevTools (F12): Sources panel for breakpoints, Watch for variables, step-through execution
- Console methods:
log/warn/error/table/group/time/timeEndboost debugging efficiency
📝 Exercises
- Write a function
safeDivide(a, b)that uses try...catch to handle division by zero (hint: dividing by zero in JS doesn't throw — you need to check and throw yourself). Return the result or an error message. - Write a function
safeJSONParse(str)that parses a JSON string. On failure, return{ success: false, error: <error message> }. On success, return{ success: true, data: <parsed result> }. - Write a function
retry(fn, times): executefn, and if it throws, retry up totimestimes. If all attempts fail, throw the last error. Implement with try...catch.