Ở tập trước, bạn đã cho mèo kế thừa khả năng, kiểm soát bí mật bằng private field, xài getter/setter như lễ tân hoàng gia. Nhưng class cũng như mèo: cứ tưởng đã hiểu hết nhưng...
🧩 Vấn đề: Mèo con cần học tiếng... từ mẹ
Tưởng tượng bạn có một dòng họ mèo truyền đời: đời mẹ truyền lại tiếng kêu, đời con cải biên. Bạn thử:
class MeoMe {
keu() {
console.log('MeoMe: Meo...meo...');
}
}
class MeoCon extends MeoMe {
keu() {
console.log('MeoCon: Meo meo remix!');
// Gọi lại tiếng gốc
super.keu();
}
}
const con = new MeoCon();
con.keu();
Và nó chạy như ý:
MeoCon: Meo meo remix!
MeoMe: Meo...meo...
✅ Giải pháp: Gọi cha bằng super
Người thông minh như bạn chắc chắn nghĩ ra rằng:
“Nếu kế thừa rồi thì phải có cách gọi lại hàm của cha chứ?”
Đúng vậy! Từ khóa super
chính là cánh cổng kết nối lên thế hệ trước:
- Trong constructor → gọi hàm khởi tạo cha
- Trong method → gọi lại phương thức cha đã bị override
class Meo {
constructor(ten) {
this.ten = ten;
}
}
class MeoCon extends Meo {
constructor(ten) {
super(ten); // Không có dòng này là toang
console.log(`Chào, tôi là ${this.ten}`);
}
}
🧩 Vấn đề tiếp theo: Làm sao biết dòng dõi của mèo?
Bạn có nhiều loại mèo:
- MeoTay
- MeoTa
- MeoFake
- MeoMộtPhút
Bạn nhận được một con mèo, nhưng muốn chắc chắn nó thuộc giống gì. Bạn thử:
if (meo instanceof MeoTa) {
console.log('Chính hiệu MeoTa!');
}
✅ Giải pháp: Kiểm tra huyết thống bằng instanceof
Người thông minh như bạn nghĩ ngay:
“Cần test xem một con mèo là con cháu ai.”
Từ khóa instanceof
chính là giấy khai sinh trong JS:
meo instanceof MeoTa; // true nếu meo sinh ra từ class MeoTa hoặc con cháu của nó
Lưu ý: nếu object được clone thủ công kiểu “hàng chợ” thì
instanceof
có thể bị đánh lừa. Nhưng trong hầu hết trường hợp “mèo nhà lành”, bạn xài được vô tư.
🧩 Vấn đề cuối: Gọi mèo mà mèo không nghe
Tưởng tượng bạn gắn nút trên web để gọi mèo:
class Meo {
constructor(ten) {
this.ten = ten;
}
keu() {
console.log(`${this.ten}: Meo meo!`);
}
}
const meo = new Meo('Tom');
document.getElementById('btn').addEventListener('click', meo.keu);
Bạn click.
Không tiếng mèo. Chỉ có tiếng lỗi:
Cannot read properties of undefined (reading 'ten')
🐱 Vấn đề: this
phản chủ
Bạn vừa bị cú "mất gốc this
" – một trong những chiêu khó chịu nhất trong JS.
Khi bạn truyền method keu
mà không gọi nó (()
), bạn không mang theo this
. Và this
trôi mất như mèo leo hàng rào – về đâu không rõ.
✅ Giải pháp: Trị this
bằng cách buộc nó ở nhà
Người thông minh như bạn chắc chắn nghĩ ra rằng:
“Phải làm sao để this
luôn trỏ đúng object của mình?”
Có nhiều cách “trói” this
:
1. Dùng arrow function trong constructor
class Meo {
constructor(ten) {
this.ten = ten;
this.keu = () => {
console.log(`${this.ten}: Meo meo!`);
};
}
}
2. Dùng .bind(this)
để khóa chặt
class Meo {
constructor(ten) {
this.ten = ten;
this.keu = this.keu.bind(this);
}
keu() {
console.log(`${this.ten}: Meo meo!`);
}
}
3. Dùng arrow function ở chỗ gọi
btn.addEventListener('click', () => meo.keu());
Nhẹ, nhanh, gọn – nhưng không dùng được nếu bạn cần .removeEventListener
.
🧾 Tổng kết tập 3: Dòng dõi - Huyết thống - Quyền kiểm soát
Tính năng | Công dụng |
---|---|
super |
Gọi method hoặc constructor từ class cha |
instanceof |
Kiểm tra object có thuộc class nào đó không |
this trong callback |
Cần “trị” để không bị lạc gốc khi gọi hàm ngoài context |