Khái niệm
JavaScript sử dụng Prototypal Inheritance (kế thừa dựa trên nguyên mẫu) thay vì Class-based inheritance như Java/C++. Đối tượng kế thừa từ đối tượng khác thông qua chuỗi prototype (__proto__).
Cách thực hiện (ES5 - Constructor Function)
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>JS Inheritance</title>
<style>
body { font-family: 'Segoe UI', sans-serif; padding: 20px; }
.result { font-size: 16px; color: #6a1b9a; font-weight: 500; margin: 20px 0; padding: 15px; background: #f3e5f5; border-radius: 4px; min-height: 100px; white-space: pre-wrap; }
button { padding: 10px 20px; background: #1976d2; color: white; border: none; border-radius: 4px; cursor: pointer; }
</style>
</head>
<body>
<h1>Kế thừa trong JavaScript (Prototype)</h1>
<div class="result" id="result"></div>
<button id="btn">TẠO ĐỐI TƯỢNG & GỌI PHƯƠNG THỨC KẾ THỪA</button>
<h3>Nhấn nút để tạo person1, person2 và gọi welcome() kế thừa</h3>
<script>
const btnEle = document.getElementById('btn');
const resEle = document.getElementById('result');
// Constructor function (Parent)
function Person(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
}
// Thêm method vào prototype - CHIA SẺ cho tất cả instance
Person.prototype.welcome = function() {
resEle.textContent += `Welcome ${this.name} age: ${this.age} city: ${this.city}\n`;
};
btnEle.addEventListener('click', () => {
resEle.textContent = '';
// Tạo instance
const person1 = new Person('Rohan', 22, 'Delhi');
person1.welcome(); // Gọi method từ prototype
const person2 = new Person('Shawn', 19, 'England');
person2.welcome();
// Kiểm tra prototype chain
console.log(person1.__proto__ === Person.prototype); // true
console.log(person1.constructor === Person); // true
});
</script>
</body>
</html>
Kết quả
Welcome Rohan age: 22 city: Delhi Welcome Shawn age: 19 city: England
ES6 Class Syntax (Syntax sugar)
class Person {
constructor(name, age, city) {
this.name = name;
this.age = age;
this.city = city;
}
welcome() {
console.log(`Welcome ${this.name} age: ${this.age} city: ${this.city}`);
}
}
// Kế thừa với extends
class Student extends Person {
constructor(name, age, city, studentId) {
super(name, age, city); // Gọi constructor cha
this.studentId = studentId;
}
study() {
console.log(`${this.name} đang học...`);
}
}
const student = new Student('Minh', 20, 'Hanoi', 'SV001');
student.welcome(); // Từ class cha
student.study(); // Method riêng
Prototype Chain
student → Student.prototype → Person.prototype → Object.prototype → null
Best Practices
- Định nghĩa method trên
prototype, không phải trong constructor (tiết kiệm bộ nhớ) - Dùng
Object.create()cho kế thừa thuần prototype - Ưu tiên
classsyntax cho code hiện đại - Tránh sửa đổi
Object.prototypehoặc built-in prototypes