404 Not Found

404 Not Found


nginx

JavaScript Errors and Debugging

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.

📖 Summary

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.

try...catch...finally

Use try...catch to catch runtime errors and prevent your program from crashing:

HTML
<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:

throw — Manually Throwing Errors

try...catch can only catch runtime errors, but business logic errors need to be thrown manually:

HTML
<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.

Custom Error Messages

Use subclasses of Error or custom properties to provide richer error information:

HTML
<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>

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.

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.

Debugging Tips


Example: try/catch for JSON Parsing

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>JSON Parsing</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    .demo { max-width: 600px; margin: 16px auto; }
    textarea { width: 100%; height: 120px; padding: 12px; font-size: 14px; font-family: monospace; border: 2px solid #ccc; border-radius: 6px; resize: vertical; box-sizing: border-box; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; margin: 8px 4px; }
    .parse { background: #4a90d9; color: #fff; }
    .parse:hover { background: #357abd; }
    .bad { background: #d9534f; color: #fff; }
    .bad:hover { background: #c9302c; }
    .result { margin-top: 16px; padding: 16px; border-radius: 8px; }
    .success { background: #d4edda; border: 2px solid #5cb85c; }
    .error-box { background: #f8d7da; border: 2px solid #d9534f; }
    .error-type { font-weight: bold; color: #721c24; }
    .error-msg { margin-top: 4px; color: #721c24; }
  </style>
</head>
<body>
  <h2 style="text-align:center;">JSON Parse Error Handling</h2>
  <div class="demo">
    <textarea id="jsonInput">{
  "name": "Alice",
  "age": 20,
  "skills": ["JavaScript", "HTML", "CSS"]
}</textarea>
    <div style="text-align:center;">
      <button class="parse" id="parseBtn">Parse JSON</button>
      <button class="bad" id="badBtn">Insert Invalid JSON</button>
    </div>
    <div id="result"></div>
  </div>
  <script>
    function parseJSON(jsonStr) {
      try {
        const data = JSON.parse(jsonStr);
        return { success: true, data: data };
      } catch (error) {
        return { success: false, name: error.name, message: error.message };
      }
    }

    document.getElementById("parseBtn").addEventListener("click", function() {
      var input = document.getElementById("jsonInput").value;
      var result = parseJSON(input);
      var output = document.getElementById("result");

      if (result.success) {
        output.className = "result success";
        output.innerHTML = "<strong>Parse successful!</strong><pre>" +
          JSON.stringify(result.data, null, 2) + "</pre>";
      } else {
        output.className = "result error-box";
        output.innerHTML = '<div class="error-type">' + result.name +
          '</div><div class="error-msg">' + result.message + '</div>';
      }
    });

    document.getElementById("badBtn").addEventListener("click", function() {
      document.getElementById("jsonInput").value = '{name: "Alice", age: 20}';
    });
  </script>
</body>
</html>
▶ Try it Yourself

Example: Custom Errors and Form Validation

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Custom Errors</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    .form { max-width: 440px; margin: 16px auto; padding: 24px; background: #f9f9f9; border-radius: 12px; }
    .row { margin: 12px 0; }
    label { display: block; margin-bottom: 4px; font-weight: bold; }
    input { width: 100%; padding: 10px 12px; font-size: 16px; border: 2px solid #ccc; border-radius: 6px; box-sizing: border-box; }
    input.valid { border-color: #5cb85c; }
    input.invalid { border-color: #d9534f; }
    .field-error { color: #d9534f; font-size: 13px; margin-top: 2px; min-height: 20px; }
    button { padding: 10px 24px; font-size: 16px; border: none; border-radius: 6px; cursor: pointer; background: #4a90d9; color: #fff; width: 100%; margin-top: 8px; }
    button:hover { background: #357abd; }
    .global-msg { margin-top: 12px; padding: 12px; border-radius: 6px; text-align: center; }
    .global-ok { background: #d4edda; color: #155724; }
    .global-fail { background: #f8d7da; color: #721c24; }
  </style>
</head>
<body>
  <h2 style="text-align:center;">Custom Error Validation</h2>
  <div class="form">
    <div class="row">
      <label>Username (3–20 characters):</label>
      <input type="text" id="username" placeholder="Enter username" />
      <div class="field-error" id="usernameErr"></div>
    </div>
    <div class="row">
      <label>Age (0–150):</label>
      <input type="text" id="age" placeholder="Enter age" />
      <div class="field-error" id="ageErr"></div>
    </div>
    <div class="row">
      <label>Email:</label>
      <input type="text" id="email" placeholder="Enter email" />
      <div class="field-error" id="emailErr"></div>
    </div>
    <button id="submitBtn">Submit</button>
    <div class="global-msg" id="globalMsg"></div>
  </div>
  <script>
    class ValidationError extends Error {
      constructor(field, message) {
        super(message);
        this.name = "ValidationError";
        this.field = field;
      }
    }

    function validateUsername(value) {
      if (!value.trim()) throw new ValidationError("username", "Username cannot be empty");
      if (value.trim().length < 3) throw new ValidationError("username", "Username must be at least 3 characters");
      if (value.trim().length > 20) throw new ValidationError("username", "Username must be at most 20 characters");
    }

    function validateAge(value) {
      if (!value.trim()) throw new ValidationError("age", "Age cannot be empty");
      var num = Number(value);
      if (isNaN(num)) throw new ValidationError("age", "Please enter a valid number");
      if (num < 0 || num > 150) throw new ValidationError("age", "Age range: 0–150");
      if (!Number.isInteger(num)) throw new ValidationError("age", "Age must be an integer");
    }

    function validateEmail(value) {
      if (!value.trim()) throw new ValidationError("email", "Email cannot be empty");
      if (!value.includes("@")) throw new ValidationError("email", "Email must contain @");
      if (!value.includes(".")) throw new ValidationError("email", "Invalid email format");
    }

    var validators = {
      username: validateUsername,
      age: validateAge,
      email: validateEmail
    };

    function clearErrors() {
      ["username", "age", "email"].forEach(function(field) {
        document.getElementById(field).className = "";
        document.getElementById(field + "Err").textContent = "";
      });
      document.getElementById("globalMsg").innerHTML = "";
      document.getElementById("globalMsg").className = "global-msg";
    }

    document.getElementById("submitBtn").addEventListener("click", function() {
      clearErrors();
      var hasError = false;

      ["username", "age", "email"].forEach(function(field) {
        var value = document.getElementById(field).value;
        try {
          validators[field](value);
          document.getElementById(field).className = "valid";
        } catch (e) {
          hasError = true;
          document.getElementById(field).className = "invalid";
          document.getElementById(field + "Err").textContent =
            e.name + ": " + e.message;
        }
      });

      var msg = document.getElementById("globalMsg");
      if (hasError) {
        msg.className = "global-msg global-fail";
        msg.textContent = "Form has errors — please fix and retry";
      } else {
        msg.className = "global-msg global-ok";
        msg.textContent = "All fields passed validation!";
      }
    });
  </script>
</body>
</html>
▶ Try it Yourself

Example: Error Types Quick Reference and console Methods

HTML
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Error Types & Console</title>
  <style>
    body { font-family: sans-serif; padding: 20px; }
    .section { margin: 20px 0; }
    table { border-collapse: collapse; width: 100%; max-width: 700px; }
    td, th { border: 1px solid #ddd; padding: 10px 14px; text-align: left; }
    th { background: #4a90d9; color: #fff; }
    .trigger { background: #f8d7da; }
    .safe { background: #d4edda; }
    button { padding: 6px 16px; border: none; border-radius: 4px; cursor: pointer; margin: 2px; font-size: 14px; }
    .btn-err { background: #d9534f; color: #fff; }
    .btn-safe { background: #5cb85c; color: #fff; }
    .btn-info { background: #5bc0de; color: #fff; }
    .output { margin-top: 12px; padding: 12px; background: #1a1a2e; color: #e0e0e0; border-radius: 6px; font-family: monospace; font-size: 13px; min-height: 60px; max-height: 200px; overflow-y: auto; }
    .log-line { margin: 2px 0; }
    .log-warn { color: #f0ad4e; }
    .log-error { color: #d9534f; }
    .log-info { color: #5bc0de; }
  </style>
</head>
<body>
  <h2>Error Types & Console Methods Demo</h2>

  <div class="section">
    <h3>Common Error Types</h3>
    <table>
      <tr><th>Error Type</th><th>Trigger Code</th><th>try/catch Result</th></tr>
      <tr class="trigger"><td>SyntaxError</td><td><code>JSON.parse("{bad")</code></td><td id="r1"></td></tr>
      <tr class="trigger"><td>ReferenceError</td><td><code>notExistVar</code></td><td id="r2"></td></tr>
      <tr class="trigger"><td>TypeError</td><td><code>undefined.toString()</code></td><td id="r3"></td></tr>
      <tr class="trigger"><td>RangeError</td><td><code>new Array(-1)</code></td><td id="r4"></td></tr>
    </table>
  </div>

  <div class="section">
    <h3>console Methods (Simulated Output)</h3>
    <button class="btn-info" onclick="simLog('log', 'Regular log')">console.log</button>
    <button class="btn-info" onclick="simLog('warn', 'Warning message')">console.warn</button>
    <button class="btn-err" onclick="simLog('error', 'Error message')">console.error</button>
    <button class="btn-info" onclick="simLog('info', 'Info message')">console.info</button>
    <button class="btn-safe" onclick="simTable()">console.table</button>
    <button class="btn-safe" onclick="simTime()">console.time</button>
    <button class="btn-info" onclick="clearSim()">Clear</button>
    <div class="output" id="simConsole"></div>
  </div>

  <script>
    var tests = [
      function() { JSON.parse("{bad"); },
      function() { notExistVar; },
      function() { var x; x.toString(); },
      function() { new Array(-1); }
    ];

    var ids = ["r1", "r2", "r3", "r4"];
    var names = ["SyntaxError", "ReferenceError", "TypeError", "RangeError"];

    tests.forEach(function(fn, i) {
      try {
        fn();
        document.getElementById(ids[i]).textContent = "Not triggered (unexpected)";
      } catch (e) {
        document.getElementById(ids[i]).innerHTML =
          '<span class="safe">' + e.name + ": " + e.message + '</span>';
      }
    });

    function simLog(type, msg) {
      var cls = type === "warn" ? "log-warn" :
                type === "error" ? "log-error" : "log-info";
      var prefix = type === "warn" ? "⚠" :
                   type === "error" ? "✖" : "ℹ";
      addLine(prefix + " " + msg, cls);
      if (type !== "error") {
        console[type](msg);
      }
    }

    function simTable() {
      var data = [
        { name: "Alice", age: 20, score: 90 },
        { name: "Bob", age: 22, score: 85 },
        { name: "Charlie", age: 21, score: 95 }
      ];
      addLine("console.table:", "log-info");
      data.forEach(function(d) {
        addLine("  " + d.name + " | " + d.age + " | " + d.score, "log-info");
      });
      console.table(data);
    }

    function simTime() {
      console.time("demo");
      var sum = 0;
      for (var i = 0; i < 1000000; i++) { sum += i; }
      console.timeEnd("demo");
      addLine("⏱ console.time/timeEnd: 1,000,000 additions done", "log-info");
    }

    function addLine(text, cls) {
      var div = document.getElementById("simConsole");
      div.innerHTML += '<div class="log-line ' + (cls || "") + '">' + text + '</div>';
      div.scrollTop = div.scrollHeight;
    }

    function clearSim() {
      document.getElementById("simConsole").innerHTML = "";
    }
  </script>
</body>
</html>
▶ Try it Yourself

❓ FAQ

Q Can try...catch catch SyntaxError?
A No. 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.
Q When should I use finally?
A When you need cleanup operations to run regardless of whether an error occurred — closing files, releasing resources, hiding loading states. For most simple scenarios, catch alone is sufficient.
Q What's the difference between throw and return?
A 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.

📝 Exercises

  1. 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.
  2. 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> }.
  3. Write a function retry(fn, times): execute fn, and if it throws, retry up to times times. If all attempts fail, throw the last error. Implement with try...catch.
100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏