Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> JavaScript

ขยายคลาส Error ใน JavaScript: สร้าง Custom Error ให้ถูกต้อง


JavaScript อนุญาตให้สร้างคลาสข้อผิดพลาดแบบกำหนดเอง (Custom Error) โดยการขยาย (extends) คลาส Error ในตัว วิธีที่ดีที่สุดคือสร้างคลาสลูกที่เรียก super(message) และตั้งค่า this.name ให้เป็นชื่อที่สื่อความหมาย เพื่อให้識別ง่ายใน catch และ stack trace

ตัวอย่างโค้ด

<!DOCTYPE html>
<html lang="th">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>ขยาย Error Class</title>
  <style>
    body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; }
    .result { font-size: 18px; font-weight: 500; color: rebeccapurple; }
  </style>
</head>
<body>
  <h1>ขยาย JavaScript Error Class</h1>
  <div class="result"></div>
  <button class="Btn">คลิกที่นี่</button>
  <h3>กดปุ่มเพื่อสร้างและโยน Custom Error</h3>
  <script>
    const resEle = document.querySelector(".result");
    const btnEle = document.querySelector(".Btn");
    // Custom Error Class - วิธีที่ถูกต้อง
    class CustomError extends Error {
      constructor(message) {
        super(message);        // เรียก constructor ของ Error
        this.name = "CustomError"; // ตั้งชื่อเฉพาะตัว
        // ES2022: สามารถเพิ่ม cause ได้
        // super(message, { cause: originalError });
      }
    }
    function test() {
      throw new CustomError("ข้อผิดพลาดใหม่ถูกโยน");
    }
    btnEle.addEventListener("click", () => {
      try {
        test();
      } catch (err) {
        resEle.innerHTML += "err.name = " + err.name + "<br>";
        resEle.innerHTML += "err.message = " + err.message + "<br>";
        resEle.innerHTML += "err instanceof Error: " + (err instanceof Error) + "<br>";
        resEle.innerHTML += "err instanceof CustomError: " + (err instanceof CustomError);
      }
    });
  </script>
</body>
</html>

ผลลัพธ์

ขยายคลาส Error ใน JavaScript: สร้าง Custom Error ให้ถูกต้อง

เมื่อกดปุ่ม "คลิกที่นี่":

ขยายคลาส Error ใน JavaScript: สร้าง Custom Error ให้ถูกต้อง

รูปแบบ Custom Error แบบสมบูรณ์ (Production Ready)

class AppError extends Error {
  constructor(message, options = {}) {
    super(message, options); // ES2022: สรอง cause
    this.name = this.constructor.name; // ใช้ชื่อคลาสอัตโนมัติ
    this.code = options.code || "APP_ERROR";
    this.statusCode = options.statusCode || 500;
    this.details = options.details || null;
    // Capture stack trace (V8/Node.js)
    if (Error.captureStackTrace) {
      Error.captureStackTrace(this, this.constructor);
    }
  }
}

// ใช้งาน
class ValidationError extends AppError {
  constructor(message, details) {
    super(message, { code: "VALIDATION_ERROR", statusCode: 400, details });
  }
}

class NotFoundError extends AppError {
  constructor(resource) {
    super(`${resource} not found`, { code: "NOT_FOUND", statusCode: 404 });
  }
}

// ตรวจสอบประเภท
try {
  throw new ValidationError("Email ไม่ถูกต้อง", { field: "email" });
} catch (err) {
  if (err instanceof ValidationError) {
    console.log("Validation failed:", err.details);
  } else if (err instanceof AppError) {
    console.log("App error:", err.code);
  }
}

ทำไมต้อง extends Error?

  • instanceof Error เป็น true — ใช้งานกับ error handling ทั่วไปได้
  • Stack trace ถูกต้อง — ชี้ไปยังจุดที่ throw จริง
  • name แสดงใน DevTools/Console ช่วย debug
  • รองรับ cause (ES2022) สำหรับ error chaining

ข้อผิดพลาดที่พบบ่อย

// ❌ ผิด: ไม่เรียก super() → stack trace แพ้, instanceof Error = false
class BadError extends Error {
  constructor(msg) { this.message = msg; this.name = "BadError"; }
}

// ❌ ผิด: ใช้ function แทน class (ES5 style) — prototype chain ซับซ้อน
function OldError(msg) { this.message = msg; }
OldError.prototype = Object.create(Error.prototype);