JavaScript
Class
Methods ใน Class
เรียนรู้การเขียน method ใน class — ฟังก์ชันที่ทำให้ instance มีพฤติกรรมของตัวเอง ตั้งแต่ syntax พื้นฐาน, การใช้ this อ่าน property, การรับ parameter, การ return ค่า, การเรียก method จากอีก method ผ่าน this.methodName() ไปจนถึงกฎสำคัญและข้อผิดพลาดที่พบบ่อย ผ่าน Lab 5 ข้อ
Method คืออะไร — ฟังก์ชันที่อยู่ใน class
**Method** คือ **ฟังก์ชันที่ประกาศไว้ใน class** — มันเป็นพฤติกรรมที่ instance ทุกตัวของ class นั้นทำได้ หลังจาก constructor สร้าง property ให้ instance แล้ว method คือสิ่งที่ทำให้ instance "ทำอะไรบางอย่าง" กับ property เหล่านั้นได้ วิธีประกาศ method: เขียนชื่อ method ตามด้วย `( )` และ `{ }` — **ไม่ต้องใช้ `function` keyword** หน้า method นี่คือ syntax shorthand ของ JavaScript class
`sayHello()` เป็น method ของ class `User` — ทุก instance เรียกใช้ได้
class User {
constructor(name) {
this.name = name;
}
sayHello() {
console.log("สวัสดี! ฉันชื่อ " + this.name);
}
}
const u = new User("สมชาย");
u.sayHello(); // "สวัสดี! ฉันชื่อ สมชาย"สังเกตว่า method `sayHello()` เขียนแค่ `sayHello() { ... }` — ไม่มี `function` keyword นำหน้า นี่คือ syntax ปกติของ method ใน class: ใช้ shorthand `methodName() { }` เสมอ
ซ้ายผิดเพราะใส่ `function` หน้า method → SyntaxError ขวาถูก — shorthand syntax
// ❌ SyntaxError
class Wrong {
function greet() {
console.log("hello");
}
}
// ✅ shorthand syntax
class Correct {
greet() {
console.log("hello");
}
}**วิธีเรียกใช้ method**: เขียน `instanceName.methodName()` — เหมือนเรียกฟังก์ชันทั่วไป แต่ต้องผ่าน instance ก่อน method เป็นของ instance — instance แต่ละตัวมี method เดียวกัน แต่ทำงานกับ property ของตัวเอง
`this` ใน method — เข้าถึง property ของ instance ตัวเอง
`this` ใน method **ชี้ไปที่ instance ที่กำลังเรียก method นั้นอยู่** — ทำให้ method อ่าน (หรือแก้ไข) property ของ instance ตัวเองได้ นี่คือกลไกหลักที่ทำให้ method "รู้ว่าเป็นของ instance ไหน": `this` ไม่ใช่ค่าคงที่ แต่มันเปลี่ยนไปตาม instance ที่เรียก
`user1.getInfo()` — `this` คือ `user1` → อ่าน `user1.name`, `user1.role` `user2.getInfo()` — `this` คือ `user2` → อ่าน `user2.name`, `user2.role`
class User {
constructor(name, role) {
this.name = name;
this.role = role;
}
getInfo() {
return this.name + " (" + this.role + ")";
}
}
const user1 = new User("สมชาย", "admin");
const user2 = new User("สมหญิง", "editor");
console.log(user1.getInfo()); // "สมชาย (admin)"
console.log(user2.getInfo()); // "สมหญิง (editor)"จากตัวอย่าง: `getInfo()` ใช้ `this.name` และ `this.role` — ค่าที่ได้จะแตกต่างไปตาม instance ที่เรียก **จำง่าย ๆ**: `this` ใน method = ใครเรียก method นั้น `this` ก็คือคนนั้น
`getPriceTag()` return string ที่สร้างจาก property หลายตัว — ใช้ `this` เพื่อดึงค่าเฉพาะของ instance นั้น
class Product {
constructor(name, price, unit) {
this.name = name;
this.price = price;
this.unit = unit;
}
getPriceTag() {
return this.name + " — " + this.price + " บาท / " + this.unit;
}
}
const p1 = new Product("เมาส์", 590, "ชิ้น");
const p2 = new Product("ข้าวสาร", 220, "กิโลกรัม");
console.log(p1.getPriceTag()); // "เมาส์ — 590 บาท / ชิ้น"
console.log(p2.getPriceTag()); // "ข้าวสาร — 220 บาท / กิโลกรัม"Method รับ parameter ได้ — ส่งข้อมูลเข้ามาตอนเรียก
Method รับ parameter ได้เหมือนฟังก์ชันทั่วไป — ใส่ `(param1, param2)` ไว้หลังชื่อ method parameter ช่วยให้ method รับข้อมูลจากภายนอกเข้ามาประมวลผลร่วมกับ property ของ instance ได้
`addScore(points)` รับจำนวนแต้ม แล้วบวกเข้า `this.score` — instance แต่ละตัวมีคะแนนของตัวเอง
class Player {
constructor(name) {
this.name = name;
this.score = 0;
}
addScore(points) {
this.score = this.score + points;
console.log(this.name + " ได้ " + points + " แต้ม คะแนนรวม: " + this.score);
}
}
const p1 = new Player("สมชาย");
const p2 = new Player("สมหญิง");
p1.addScore(10); // "สมชาย ได้ 10 แต้ม คะแนนรวม: 10"
p2.addScore(25); // "สมหญิง ได้ 25 แต้ม คะแนนรวม: 25"
p1.addScore(5); // "สมชาย ได้ 5 แต้ม คะแนนรวม: 15"`transfer(amount, toAccount)` — method ที่รับ 2 parameter: จำนวนเงินและปลายทาง
class Account {
constructor(name, balance) {
this.name = name;
this.balance = balance;
}
transfer(amount, toAccount) {
this.balance = this.balance - amount;
console.log(
"โอน " + amount + " บาท จาก " +
this.name + " → " + toAccount +
" (คงเหลือ " + this.balance + " บาท)"
);
}
}
const acc = new Account("สมชาย", 5000);
acc.transfer(1500, "สมหญิง");
// "โอน 1500 บาท จาก สมชาย → สมหญิง (คงเหลือ 3500 บาท)"**parameter ตำแหน่งของ method กับฟังก์ชันทั่วไป เหมือนกันทุกประการ** — รับกี่ตัวก็ได้, มี default value ได้, ใช้ rest parameter ได้
Method คืนค่าได้ — ใช้ `return` ส่งผลลัพธ์กลับ
Method ใช้ `return` ได้เหมือนฟังก์ชันทั่วไป — คืนค่ากลับไปยังจุดที่เรียก ในบท constructor เราเรียนว่า constructor ห้าม return (โดยปกติ) แต่ method return ได้ตามปกติ — นี่คือข้อแตกต่างสำคัญระหว่าง constructor กับ method
`getTotal()` return ราคารวม = price × quantity — ผู้เรียกเอาไปใช้ต่อได้
class CartItem {
constructor(name, price, quantity) {
this.name = name;
this.price = price;
this.quantity = quantity;
}
getTotal() {
return this.price * this.quantity;
}
}
const item = new CartItem("เมาส์", 590, 3);
const total = item.getTotal();
console.log(total); // 1770`logInfo()` — void method (ไม่มี return, แค่ console.log) `getInfo()` — return string (เอาไปใช้ต่อได้)
class User {
constructor(name, age) {
this.name = name;
this.age = age;
}
// void method — แค่พิมพ์ข้อมูล
logInfo() {
console.log(this.name + ", " + this.age + " ปี");
}
// return method — คืนข้อมูลกลับ
getInfo() {
return this.name + ", " + this.age + " ปี";
}
}
const u = new User("สมชาย", 30);
u.logInfo(); // "สมชาย, 30 ปี"
const info = u.getInfo();
console.log(info); // "สมชาย, 30 ปี"**เลือกใช้ให้เหมาะ**: void method เมื่อต้องการให้ method "ทำ" บางอย่าง (เช่น update ค่า, พิมพ์ log) และ return method เมื่อต้องการให้ method "คืนค่ากลับมา" ให้เอาไปใช้ต่อ
เรียก method จากอีก method หนึ่งด้วย `this`
ภายใน class method หนึ่งสามารถเรียกอีก method หนึ่งได้ผ่าน `this.methodName()` — ทำให้ reuse logic ได้และ method ทำงานร่วมกันได้อย่างเป็นธรรมชาติ
`getProfile()` เรียก `getFullName()` และ `getRoleLabel()` — ถ้าเปลี่ยน logic ใน method ย่อย `getProfile()` ก็เปลี่ยนตามอัตโนมัติ
class Employee {
constructor(firstName, lastName, role) {
this.firstName = firstName;
this.lastName = lastName;
this.role = role;
}
getFullName() {
return this.firstName + " " + this.lastName;
}
getRoleLabel() {
if (this.role === "admin") {
return "ผู้ดูแลระบบ";
}
return "พนักงานทั่วไป";
}
getProfile() {
return this.getFullName() + " — " + this.getRoleLabel();
}
}
const emp = new Employee("สมชาย", "ใจดี", "admin");
console.log(emp.getProfile()); // "สมชาย ใจดี — ผู้ดูแลระบบ"`getSubtotal()` ถูกเรียกจากทั้ง `getTax()` และ `getSummary()` — ไม่ต้องคำนวณซ้ำ
class Invoice {
constructor(price, quantity) {
this.price = price;
this.quantity = quantity;
}
getSubtotal() {
return this.price * this.quantity;
}
getTax() {
return this.getSubtotal() * 0.07;
}
getSummary() {
return (
"ยอดรวม: " +
this.getSubtotal() +
" บาท (ภาษี " +
this.getTax() +
" บาท)"
);
}
}
const inv = new Invoice(500, 10);
console.log(inv.getSummary());
// "ยอดรวม: 5000 บาท (ภาษี 350 บาท)"การเรียก method ด้วย `this.methodName()` เป็น pattern สำคัญที่ใช้บ่อยมากใน class จริง — ตั้งแต่การ reuse logic เล็ก ๆ ไปจนถึงการจัดโครงสร้าง code ใน class ใหญ่
กฎสำคัญของ method
| กฎ | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| ห้ามใช้ `function` keyword | method ใน class ใช้ shorthand `methodName() { }` — ใส่ `function` จะเกิด SyntaxError | `greet() { }` ✅ / `function greet() { }` ❌ |
| ต้องใช้ `this.` หน้า property | ภายใน method ต้องใช้ `this.propertyName` — ลืม `this.` จะเป็น local variable ที่หายไป | `this.name` ✅ / `name` เฉย ๆ ❌ |
| แต่ละ instance แชร์ method ร่วมกัน | method ถูกแชร์ผ่าน prototype — 100 instances = 1 method copy ไม่ใช่สำเนาแยก | ประหยัด memory |
| `this` ขึ้นอยู่กับผู้เรียก | method เดียวกัน เรียกจากคนละ instance — `this` จะเป็นคนละ object | `u1.getInfo()` → `this` = u1 / `u2.getInfo()` → `this` = u2 |
| ห้ามใส่ `,` คั่นระหว่าง method | method ใน class ไม่ต้องคั่นด้วย `,` (ต่างจาก object literal) — ใส่แล้ว SyntaxError | `greet() { } work() { }` ✅ / มี `,` ❌ |
| method return ได้ตามปกติ | ใช้ `return` ได้ไม่มีข้อจำกัด — ต่างจาก constructor | `return this.price * 2;` ✅ |
ข้อผิดพลาดที่พบบ่อย
- **ใช้ `function` keyword หน้า method**: ใน class ห้ามเขียน `function greet() { }` — ใช้ shorthand `greet() { }` แทน ถ้าเผลอใช้ SyntaxError จะเกิดทันที
- **ลืม `this.` หน้า property**: `name` กับ `this.name` ไม่ใช่ตัวเดียวกัน — `this.name` คือ property ของ instance ส่วน `name` เฉย ๆ คือ local variable ที่หายไปเมื่อ method จบ
- **ใส่ `,` คั่นระหว่าง method**: ใน class ไม่ต้องมี `,` หลัง `}` ปิดของ method — ใส่แล้ว SyntaxError (นี่คือความแตกต่างจาก object literal ที่ต้องมี `,`)
- **`this` หายเมื่อ extract method ออกมาใช้**: ถ้า assign method ให้ตัวแปรแล้วเรียกตรง ๆ — `const f = obj.method; f();` — `this` จะกลายเป็น `undefined` (ใน strict mode) เพราะไม่มี instance เป็นผู้เรียก — วิธีแก้คือใช้ arrow function หรือ `bind` ซึ่งจะเรียนในบทถัด ๆ ไป
- **คิดว่า constructor คือ method ธรรมดา**: constructor ไม่ใช่ method ทั่วไป — มันถูกเรียกอัตโนมัติตอน `new`, return ค่าเองไม่ได้, มีได้ตัวเดียว — method ธรรมดา return ได้, มีกี่ตัวก็ได้
3 ข้อผิดพลาด: 1) ใส่ `,` หลัง method 2) ลืม `this.` 3) ใช้ `name` แทน `this.name`
// ❌ SyntaxError — ใส่ , หลัง method + ลืม this
class Bad {
constructor(name) {
this.name = name;
}
greet() {
console.log("สวัสดี " + name); // ❌ name คืออะไร? ไม่ใช่ this.name
}, // ❌ SyntaxError — ห้ามใส่ , หลัง method
work() {
console.log(this.name + " ทำงาน");
}
}