Prototype Inheritance (hay kế thừa prototype) trong JavaScript là cơ chế mà các đối tượng có thể “thừa hưởng” các thuộc tính và phương thức từ các đối tượng khác thông qua chuỗi prototype. Đây là một tính năng quan trọng trong mô hình lập trình hướng đối tượng (OOP) của JavaScript.
Trong JavaScript, mỗi đối tượng có một thuộc tính ẩn gọi là [[Prototype]], nó tham chiếu đến một đối tượng khác, thường được gọi là prototype. Khi bạn truy cập một thuộc tính hoặc phương thức của đối tượng, JavaScript sẽ kiểm tra xem đối tượng có thuộc tính hoặc phương thức đó không. Nếu không, nó sẽ tìm kiếm trong đối tượng prototype mà đối tượng này liên kết đến. Quá trình tìm kiếm này tiếp diễn cho đến khi tìm thấy thuộc tính hoặc phương thức, hoặc cho đến khi prototype cuối cùng (thường là null) được kiểm tra.
function Person(name, age) {
this.name = name;
this.age = age;
}
// Thêm một phương thức vào prototype của Person
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};
Trong ví dụ trên:
Person là một hàm khởi tạo (constructor function).sayHello được thêm vào prototype của Person, nghĩa là tất cả các đối tượng được tạo từ Person sẽ có quyền truy cập vào phương thức này thông qua kế thừa prototype.const person1 = new Person("Alice", 25);
person1.sayHello(); // "Hello, my name is Alice and I am 25 years old."
Ở đây:
person1.sayHello() được gọi, JavaScript sẽ tìm kiếm phương thức sayHello trong đối tượng person1. Vì person1 không có phương thức này trực tiếp, JavaScript sẽ kiểm tra trong prototype của person1, đó chính là prototype của Person. Tại đây, nó sẽ tìm thấy sayHello và thực thi nó.console.log(person1.__proto__ === Person.prototype); // true console.log(Person.prototype.__proto__ === Object.prototype); // true
person1.__proto__ (hoặc [[Prototype]]) trỏ tới Person.prototype.Person.prototype.__proto__ trỏ tới Object.prototype, vì mọi đối tượng trong JavaScript cuối cùng đều kế thừa từ Object.Object là null.function Animal(type) {
this.type = type;
}
Animal.prototype.getType = function() {
return this.type;
};
function Dog(name) {
this.name = name;
}
// Kế thừa từ Animal
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log("Woof! My name is " + this.name);
};
const myDog = new Dog("Buddy");
myDog.type = "Dog";
myDog.bark(); // "Woof! My name is Buddy"
console.log(myDog.getType()); // "Dog"
Animal có một thuộc tính type và một phương thức getType trong prototype.Dog có một thuộc tính name. Nó kế thừa từ Animal bằng cách sử dụng Object.create(Animal.prototype), nghĩa là Dog có quyền truy cập vào tất cả các phương thức của Animal.bark được thêm trực tiếp vào prototype của Dog.constructor:Object.create để kế thừa từ Animal, giá trị của Dog.prototype.constructor sẽ bị thay đổi. Do đó, ta cần gán lại giá trị Dog.prototype.constructor = Dog để đảm bảo đối tượng được tạo từ Dog sẽ có constructor đúng.Khi bạn truy cập một thuộc tính hoặc phương thức của một đối tượng, JavaScript sẽ duyệt qua chuỗi prototype (prototype chain). Quá trình này diễn ra như sau:
__proto__ hoặc [[Prototype]]).null hoặc tìm thấy thuộc tính/method.Prototype Inheritance trong JavaScript là cơ chế cho phép các đối tượng kế thừa thuộc tính và phương thức từ các đối tượng khác thông qua prototype. Điều này giúp tối ưu hóa bộ nhớ và cho phép chia sẻ phương thức giữa các đối tượng. Tuy nhiên, nó cũng có những nhược điểm liên quan đến tính dễ hiểu và khả năng bảo mật của dữ liệu.