4.1 Kế thừa — dễ hiểu thôi mà
Kế thừa là một khái niệm cơ bản trong lập trình hướng đối tượng (OOP), cho phép một class (gọi là class con hoặc subclass) thừa kế các thuộc tính và phương thức của một class khác (gọi là class cha hoặc superclass).
Cách tiếp cận này giúp tạo ra các class tổng quát hơn và tái sử dụng code, làm cho tổ chức và bảo trì code dễ dàng hơn.
Tại sao cần kế thừa?
Giả sử bạn cần viết một đoạn code, và bạn quyết định làm điều đó qua một class. Sau đó, bạn phát hiện ra rằng trong dự án của mình đã có một class thực hiện gần như mọi thứ bạn cần. Bạn có thể sao chép mã của class đó vào class của mình và sử dụng thoải mái.
Hoặc bạn có thể "như là sao chép". Bạn có thể khai báo class đó là cha của class của bạn, và khi đó JavaScript sẽ thêm hành vi của class cha vào class con của bạn.
Hãy tưởng tượng bạn là tự nhiên và muốn tạo ra một Con chó. Điều gì sẽ nhanh hơn: tạo con chó từ vi khuẩn trong một tỷ năm hay thuần hóa sói trong 200 nghìn năm?
4.2 Khái niệm kế thừa qua prototype
Kế thừa qua prototype trong JavaScript là một trong những cơ chế chính, cho phép các object thừa kế thuộc tính và phương thức từ các object khác. Điều này cho phép tạo ra các hệ thống phân cấp object phức tạp và tái sử dụng code.
Mỗi object trong JavaScript đều có một thuộc tính ẩn là [[Prototype]], chỉ đến prototype của nó. Prototype được sử dụng để thực hiện kế thừa, cho phép các object thừa kế thuộc tính và phương thức từ các object khác.
Ví dụ kế thừa đơn giản
Bước 1: Tạo object cơ bản
const animal = {
eat() {
console.log('Eating...');
},
sleep() {
console.log('Sleeping...');
}
};
Bước 2: Tạo object con
const dog = Object.create(animal);
dog.bark = function() {
console.log('Barking...');
};
Bước 3: Sử dụng các thuộc tính và phương thức thừa kế
dog.eat(); // Sẽ hiển thị: Eating...
dog.sleep(); // Sẽ hiển thị: Sleeping...
dog.bark(); // Sẽ hiển thị: Barking...
Trong ví dụ này, object dog
thừa kế các phương thức eat()
và sleep()
từ object
animal
, và thêm phương thức của riêng nó — bark()
.
4.3 Kế thừa sâu qua prototype
Chuỗi prototype
Trong JavaScript, kế thừa có thể phức tạp hơn khi các object kế thừa từ nhau, tạo thành một chuỗi prototype.
Ví dụ chuỗi prototype
Trong ví dụ này, object dog
kế thừa từ mammal
, và mammal
kế thừa từ
animal
, tạo thành một chuỗi prototype mà dog
có quyền truy cập vào tất cả các phương thức
của mammal
và animal
.
const animal = {
eat() {
console.log('Eating...');
}
};
const mammal = Object.create(animal);
mammal.walk = function() {
console.log('Walking...');
};
const dog = Object.create(mammal);
dog.bark = function() {
console.log('Barking...');
};
dog.eat(); // Sẽ hiển thị: Eating...
dog.walk(); // Sẽ hiển thị: Walking...
dog.bark(); // Sẽ hiển thị: Barking...
Kiểm tra chuỗi prototype
Phương thức isPrototypeOf()
cho phép kiểm tra một object có phải là prototype của một object khác hay không.
Ví dụ:
console.log(animal.isPrototypeOf(mammal)); // Sẽ hiển thị: true
console.log(mammal.isPrototypeOf(dog)); // Sẽ hiển thị: true
console.log(animal.isPrototypeOf(dog)); // Sẽ hiển thị: true
4.4 Ghi đè phương thức
Kế thừa qua prototype không chỉ cho phép thêm các phương thức mới mà còn ghi đè các phương thức hiện có.
Ví dụ ghi đè phương thức
Trong ví dụ này, phương thức speak()
trong object dog
ghi đè phương thức speak()
trong object animal
:
const animal = {
speak() {
console.log('Animal speaks');
}
};
const dog = Object.create(animal);
dog.speak = function() {
console.log('Dog barks');
};
animal.speak(); // Sẽ hiển thị: Animal speaks
dog.speak(); // Sẽ hiển thị: Dog barks
Gọi phương thức của object cha
Để gọi phương thức của object cha trong JavaScript, bạn có thể sử dụng phương thức call()
hoặc apply()
.
Ví dụ:
const animal = {
speak() {
console.log('Animal speaks');
}
};
const dog = Object.create(animal);
dog.speak = function() {
animal.speak.call(this);
console.log('Dog barks');
};
dog.speak();
// Sẽ hiển thị:
// Animal speaks
// Dog barks
4.5 Sử dụng chuyên sâu kế thừa qua prototype
Mở rộng các object dựng sẵn
Bạn có thể mở rộng các object dựng sẵn của JavaScript bằng cách thêm phương thức vào prototype của chúng.
Ví dụ:
Array.prototype.sum = function() {
return this.reduce((acc, value) => acc + value, 0);
};
const numbers = [1, 2, 3, 4, 5];
console.log(numbers.sum()); // Sẽ hiển thị: 15
Tạo các hệ thống phân cấp đa cấp
Bạn có thể tạo ra các hệ thống phân cấp đa cấp phức tạp hơn với kế thừa qua prototype.
Ví dụ:
const livingBeing = {
breathe() {
console.log('Breathing...');
}
};
const animal = Object.create(livingBeing);
animal.eat = function() {
console.log('Eating...');
};
const mammal = Object.create(animal);
mammal.walk = function() {
console.log('Walking...');
};
const dog = Object.create(mammal);
dog.bark = function() {
console.log('Barking...');
};
dog.breathe(); // Sẽ hiển thị: Breathing...
dog.eat(); // Sẽ hiển thị: Eating...
dog.walk(); // Sẽ hiển thị: Walking...
dog.bark(); // Sẽ hiển thị: Barking...
GO TO FULL VERSION