Prototype trong JavaScript là một thuộc tính của tất cả các đối tượng được tạo ra bởi constructor hoặc object literals. Nó cho phép chúng ta thêm các thuộc tính và phương thức mới cho các đối tượng cụ thể hoặc tất cả các đối tượng tạo ra từ một constructor nhất định.
Các bài viết liên quan:
Ví dụ, prototype của constructor Person sẽ chứa thuộc tính và phương thức mà tất cả các đối tượng tạo ra từ constructor đó sẽ kế thừa. Chúng ta có thể thêm thuộc tính và phương thức mới cho prototype để mở rộng hoặc chỉnh sửa hành vi của tất cả các đối tượng tạo ra từ constructor đó.
Prototype còn cung cấp một cách thực hiện kế thừa động trong JavaScript, cho phép chúng ta tạo ra các đối tượng mới từ các đối tượng cũ và kế thừa tính năng từ các đối tượng cha.
Vì sao nên sử dụng prototype?
Sử dụng prototype trong JavaScript cung cấp nhiều lợi ích như sau:
- Kế thừa động: Prototype cho phép chúng ta tạo ra các đối tượng mới từ các đối tượng cũ và kế thừa tính năng từ các đối tượng cha.
- Mở rộng hành vi: Chúng ta có thể thêm thuộc tính và phương thức mới cho prototype để mở rộng hoặc chỉnh sửa hành vi của tất cả các đối tượng tạo ra từ constructor đó.
- Giảm sự lặp lại: Prototype cho phép chúng ta chia sẻ thuộc tính và phương thức giữa các đối tượng, giảm sự lặp lại và tăng tính năng của code.
- Tối ưu hóa hiệu suất: Sử dụng prototype cho phép chúng ta tối ưu hóa hiệu suất bằng cách chia sẻ thuộc tính và phương thức giữa các đối tượng thay vì tạo ra các bản sao mới cho mỗi đối tượng riêng lẻ.
Ngoài ra, sử dụng prototype còn giúp tiết kiệm bộ nhớ vì các đối tượng có thể chia sẻ cùng một prototype, giúp giảm số lượng bộ nhớ được sử dụng.
Sử dụng prototype cũng giúp tăng tính minh bạch và dễ dàng quản lý trong việc phân quyền truy cập vào các thuộc tính và phương thức của đối tượng.
Sử dụng prototype trong JavaScript như thế nào ?
Sử dụng prototype trong JavaScript có thể thực hiện thông qua các cách sau:
- Sử dụng từ khóa “prototype” để thêm thuộc tính và phương thức mới cho prototype của một constructor. Ví dụ:
function MyObject() {} MyObject.prototype.myMethod = function() {};
- Sử dụng Object.create() để tạo ra một đối tượng mới với prototype được chỉ định. Ví dụ:
let myObject = Object.create(Object.prototype);
- Sử dụng class để tạo ra một constructor và kế thừa prototype từ lớp cha. Ví dụ:
class MyObject extends Object {}
- Sử dụng object spread operator để sao chép các thuộc tính từ một đối tượng khác vào prototype của một đối tượng. Ví dụ:
let myObject = {...Object.prototype}
- Sử dụng Object.setPrototypeOf() để thay đổi prototype của một đối tượng. Ví dụ:
let myObject = {}; Object.setPrototypeOf(myObject, Object.prototype);
Sau khi sử dụng các cách trên, bạn có thể truy cập các thuộc tính và phương thức được thêm vào prototype bằng cách sử dụng “.” hoặc “[]” operator. Ví dụ:
let myObject = new MyObject(); console.log(myObject.myMethod); let myObject = Object.create(Object.prototype); console.log(myObject['toString']);
Trong trường hợp sử dụng class, thì các thuộc tính và phương thức trong prototype có thể sử dụng như các thuộc tính và phương thức của class. Ví dụ:
class MyObject extends Object { myMethod() { console.log('Hello World!'); } } let obj = new MyObject(); obj.myMethod(); // in ra "Hello World!"
Một số lưu ý khi sử dụng:
- Khi sử dụng prototype, chúng ta nên chú ý khởi tạo các thuộc tính và phương thức trong hàm constructor của class, thay vì khởi tạo trực tiếp trong prototype.
- Không nên sử dụng prototype để thay đổi các thuộc tính và phương thức của các built-in objects như Array, String, v.v.
- Chú ý khi sử dụng prototype để thay đổi các thuộc tính và phương thức của đối tượng, vì nếu thay đổi sai cách có thể gây ra lỗi logic trong chương trình.
- Chú ý khi sử dụng prototype để thêm thuộc tính và phương thức mới cho đối tượng, vì nếu trùng tên với các thuộc tính và phương thức của đối tượng cha có thể gây ra lỗi logic trong chương trình.
- Chú ý khi sử dụng prototype để thêm thuộc tính và phương thức mới cho đối tượng, vì nếu không khai báo thuộc tính và phương thức là public hoặc private sẽ dẫn đến tình trạng truy cập thuộc tính và phương thức một cách không hợp lý.
Ví dụ về các trường hợp khác khi sử dụng prototype:
Ví dụ 1: Thêm phương thức mới cho built-in Array
// Thêm phương thức shuffle cho Array Array.prototype.shuffle = function() { for (let i = this.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [this[i], this[j]] = [this[j], this[i]]; } return this; }; // Sử dụng phương thức mới const numbers = [1, 2, 3, 4, 5]; console.log(numbers.shuffle()); // [3, 2, 5, 1, 4] hoặc [4, 1, 2, 5, 3] hoặc [1, 4, 2, 5, 3] ...
Ví dụ 2: Kế thừa từ lớp cha
// Lớp cha function Person(name, age) { this.name = name; this.age = age; } Person.prototype.greet = function() { console.log(`Xin chào, tôi là ${this.name}`); }; // Lớp con kế thừa từ lớp cha function Student(name, age, major) { Person.call(this, name, age); this.major = major; } Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; // Sử dụng phương thức của lớp cha const student = new Student("John", 20, "Computer Science"); student.greet(); // Xin chào, tôi là John
Ví dụ 3: Override phương thức từ lớp cha
// Lớp cha function Shape() {} Shape.prototype.draw = function() { console.log("Vẽ hình dạng chung"); }; // Lớp con override phương thức từ lớp cha function Circle() {} Circle.prototype = Object.create(Shape.prototype); Circle.prototype.constructor = Circle; Circle.prototype.draw = function() { console.log("Vẽ hình tròn"); }; // Sử dụng phương thức của lớp con const shape = new Shape(); shape.draw(); // Vẽ hình dạng chung const circle = new Circle(); circle.draw(); // Vẽ hình
Kết luận
Prototype là một tính năng quan trọng của javascript, cho phép bạn thêm các thuộc tính và phương thức mới cho các đối tượng đã tồn tại, giúp tái sử dụng các đối tượng và giảm thiểu việc tạo các đối tượng mới. Tuy nhiên, cần lưu ý rằng sử dụng prototype không thể thay thế hoàn toàn cho việc sử dụng class trong javascript.