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.