JavaScript
Class
Constructor
เรียนรู้ constructor — method พิเศษที่ถูกรันอัตโนมัติตอน `new` ใช้กำหนดค่าเริ่มต้นให้ property ของ instance แต่ละตัว ผ่าน parameter และ logic ใน constructor
constructor คืออะไร
`constructor` คือ **method พิเศษ** ที่ถูกเรียกทำงานอัตโนมัติหนึ่งครั้งตอนสร้าง instance ด้วย `new` หน้าที่หลักของ constructor: **กำหนดค่าเริ่มต้นให้ property** ของ instance แต่ละตัว เมื่อเขียน `new ClassName(arguments)` JavaScript จะ: 1. สร้าง object เปล่าใหม่ 2. เรียก constructor พร้อมส่ง arguments ที่เราให้เข้าไป 3. constructor ใช้ `this` เพื่อเพิ่ม property ลงใน object ใหม่ 4. คืน object ที่พร้อมใช้งานกลับมา
`constructor(name)` จะรันอัตโนมัติตอน `new User('สมชาย')` — `this.name = name` คือการเพิ่ม property `name` ให้ instance ใหม่
class User {
constructor(name) {
this.name = name;
}
}
const user = new User("สมชาย");
console.log(user.name); // "สมชาย"จากตัวอย่าง: - `constructor(name)` — ประกาศ constructor ที่รับ 1 parameter - `this.name = name` — `this` คือ instance ใหม่ที่กำลังถูกสร้าง ค่านี้คือการเพิ่ม property `name` - `new User('สมชาย')` — `new` สร้าง instance → เรียก constructor โดยส่ง `'สมชาย'` เป็น `name` **constructor ไม่ใช่ method ที่เราเรียกเองโดยตรง** — JavaScript เรียกให้อัตโนมัติตอนใช้ `new`
constructor ใช้ set ค่าเริ่มต้นให้แต่ละ instance
จุดเด่นของ constructor คือ **แต่ละ instance รับค่าเริ่มต้นต่างกันได้** — ผ่าน parameter ที่ส่งตอน `new` class ที่ไม่มี constructor จะสร้าง instance ที่ property ว่างเปล่าทุกตัวเหมือนกัน constructor ทำให้เรา custom ข้อมูลตั้งแต่ตอนสร้าง instance ได้
`user1` กับ `user2` มาจาก class เดียวกัน แต่มี `name` ไม่เหมือนกัน เพราะ constructor รับ parameter คนละค่าตอน `new`
class User {
constructor(name, role) {
this.name = name;
this.role = role;
}
}
const admin = new User("สมชาย", "admin");
const member = new User("สมหญิง", "member");
console.log(admin.name, admin.role); // "สมชาย" "admin"
console.log(member.name, member.role); // "สมหญิง" "member"สังเกตว่า `admin` กับ `member` เป็น object คนละตัว — แต่โครงสร้าง property เหมือนกัน (`name`, `role`) เพราะถูกกำหนดใน constructor เดียวกัน นี่คือพลังของ class + constructor: **ออกแบบโครงสร้างครั้งเดียว แล้วสร้าง instance พร้อมข้อมูลต่างกันได้ไม่จำกัด**
class `Product` รับ `name` กับ `price` — สร้างสินค้าหลายรายการโดยใช้ constructor เดียวกัน
class Product {
constructor(name, price) {
this.name = name;
this.price = price;
}
}
const item1 = new Product("เมาส์", 590);
const item2 = new Product("คีย์บอร์ด", 1290);
const item3 = new Product("จอภาพ", 4590);
console.log(item1.price + item2.price + item3.price); // 6470กฎของ constructor
constructor มีกฎเฉพาะที่ต่างจาก method ทั่วไป:
| กฎ | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| มีได้ตัวเดียวต่อ class | ประกาศ `constructor` ซ้ำกัน 2 ครั้งจะ error `SyntaxError: A class may only have one constructor` | `class A { constructor(){} constructor(x){} }` ❌ |
| ถูกรันอัตโนมัติตอน `new` | ไม่ต้องเรียก `instance.constructor()` เอง — JavaScript จัดการให้ | `new User('สมชาย')` → constructor รันทันที |
| `this` คือ instance ใหม่ | `this` ใน constructor ชี้ไปที่ object ที่กำลังถูกสร้างด้วย `new` | `this.name = name` คือเพิ่ม property ให้ instance |
| ห้ามใช้ `return` | constructor return ค่าเองไม่ได้ — JavaScript จะ ignore `return` ที่ไม่ใช่ object และ `return` object จะทำให้ `new` คืน object นั้นแทน instance | `constructor() { return 5; }` — โดน ignore / `return {}` — ได้ object เปล่าแทน instance |
| รับ parameter ได้ตามปกติ | constructor เป็น function — รับ parameter, ใช้ default value, ทำ logic ได้ | `constructor(name = 'ไม่ระบุ') {}` |
โค้ดนี้จะ error — JavaScript ไม่อนุญาตให้มี constructor มากกว่า 1 ตัวใน class เดียวกัน
// ❌ SyntaxError: A class may only have one constructor
class Bad {
constructor(name) {
this.name = name;
}
constructor(name, age) { // ← error ตรงนี้
this.name = name;
this.age = age;
}
}**แก้ยังไงเมื่ออยากรับ parameter ได้หลายรูปแบบ**: ใช้ default parameter รวมกันใน constructor เดียว หรือใช้ `arguments.length` เช็กจำนวน parameter ที่ถูกส่งเข้ามา
รวม parameter ใน constructor เดียว — `age` มี default `0` ถ้าไม่ส่งมา
class User {
constructor(name, age = 0) {
this.name = name;
this.age = age;
}
}
const withAge = new User("สมชาย", 30);
const withoutAge = new User("สมหญิง");
console.log(withAge.name, withAge.age); // "สมชาย" 30
console.log(withoutAge.name, withoutAge.age); // "สมหญิง" 0constructor ก็คือ function — รับ parameter ได้และใส่ logic ได้
constructor ทำงานเหมือน function ปกติ — นอกจาก `this.property = value` แล้ว ยังใส่ validation, คำนวณค่า, หรือ logic ใด ๆ ก่อน set property ได้
เช็คว่า `age` ต้อง >= 0 — ถ้าไม่ใช่ ให้ default เป็น 0 พร้อมแจ้งเตือน
class Person {
constructor(name, age) {
this.name = name;
if (age >= 0) {
this.age = age;
} else {
console.log("⚠️ age ต้อง >= 0 — ตั้งเป็น 0 แทน");
this.age = 0;
}
}
}
const p1 = new Person("สมชาย", 30);
const p2 = new Person("สมหญิง", -5);
// ⚠️ age ต้อง >= 0 — ตั้งเป็น 0 แทน
console.log(p1.age); // 30
console.log(p2.age); // 0ใช้ validation ใน constructor ช่วยให้ **instance ทุกตัวมีข้อมูลที่ถูกต้องตั้งแต่ถูกสร้าง** — ไม่ต้องเช็คทีหลังตอนเรียก method constructor ยังใช้สร้าง property ที่คำนวณจาก parameter หลายตัวได้:
`fullName` เกิดจากการต่อ `firstName` + `lastName` — constructor คำนวณให้อัตโนมัติ
class Employee {
constructor(firstName, lastName, salary) {
this.firstName = firstName;
this.lastName = lastName;
this.fullName = firstName + " " + lastName;
this.salary = salary;
this.annualSalary = salary * 12;
}
}
const emp = new Employee("สมชาย", "ใจดี", 25000);
console.log(emp.fullName); // "สมชาย ใจดี"
console.log(emp.annualSalary); // 300000ข้อผิดพลาดที่พบบ่อย
- **ลืม `new` ตอนสร้าง instance**: การเรียก `const u = User('สมชาย')` โดยไม่มี `new` จะไม่สร้าง instance — `this` ใน constructor จะเป็น `undefined` (ใน strict mode) หรือ `window` (ในโหมดปกติ) และ property จะไม่ถูกเพิ่มลง instance ใหม่
- **พยายามประกาศ constructor หลายตัว**: JavaScript ไม่รองรับ constructor overloading แบบ Java/C++ — ใช้ default parameter หรือตรวจสอบ `arguments` ใน constructor ตัวเดียวแทน
- **ลืม `this`**: `name = name` (ไม่มี `this.`) จะสร้างแต่ local variable ที่หายไปเมื่อ constructor จบ — property จะไม่ถูกเพิ่มลง instance
- **ใช้ `return` ใน constructor**: constructor ถูกออกแบบให้ return instance โดยอัตโนมัติ — การใส่ `return` ทำให้พฤติกรรมเปลี่ยน `return` ค่า primitive จะถูก ignore แต่ `return` object จะทำให้ `new` คืน object นั้นแทน instance
- **constructor ทำเยอะเกิน**: ใส่ logic ซับซ้อนมากเกินไปใน constructor — เช่น อ่านไฟล์, ต่อ database, ทำ async — ทำให้การสร้าง instance ช้าและเทสยาก ควรเก็บ constructor ไว้แค่รับค่าและ set property
- **คิดว่า constructor เรียกเองได้**: `instance.constructor()` เรียกซ้ำได้ทางเทคนิคแต่ไม่ควรทำ — มันจะรัน body constructor ใหม่โดยไม่สร้าง instance ใหม่ ทำให้ logic ทำงานซ้ำโดยไม่ตั้งใจ