Hi 🤓 Cảm ơn bạn đã ghé thăm blog này, nếu những bài viết trên blog giúp ích cho bạn. Bạn có thể giúp blog hiển thị quảng cáo bằng cách tạm ngừng ad blocker 😫 và để giúp blog duy trì hoạt động nếu bạn muốn.
Cảm ơn bạn!

Bài viết hôm nay, chúng ta sẽ tìm hiểu về khái niệm prototype trong JavaScript và cách hoạt động của nó nhé 😄😄.

Prototype trong JavaScript là gì?

Trong JavaScript, một object có thể kế thừa - inherit các đặc tính của object khác thông qua một thứ gọi là prototype. Mỗi object đều có thuộc tính của nó là prototype và bản thân prototype là một object.

Ví dụ:

let website = {name: 'homiedev'};

Khi ta in object website này ra console. Bạn sẽ thấy object này có một thuộc tính gọi là prototype biểu thị bằng [[Prototype]].

example prototype JavaScript

Nguyên mẫu - prototype là một object và nó có các thuộc tính riêng của nó. Khi bạn lấy một thuộc tính của một object, nếu object có thuộc tính đó, nó sẽ trả về giá trị thuộc tính. Ví dụ:

console.log(website.name); // homiedev

JavaScript sẽ trả về giá trị của thuộc tính name như mong đợi. Tuy nhiên, nếu ta thử truy cập một thuộc tính không tồn tại trong một object, JavaScript sẽ làm một công việc đó là tìm kiếm trong prototype của object.

Nếu JavaScript không tìm thấy thuộc tính trong prototype của object, nó sẽ tiếp tục tìm kiếm trong nguyên mẫu của prototype của object cho đến khi tìm thấy thuộc tính hoặc đến cuối prototype chain.

Đối tượng prototype cũng có prototype của chính nó và cứ tiếp tục như vậy cho đến khi nó gặp null làm nguyên mẫu - prototype của nó. Vì vậy, những liên kết này được gọi là chuỗi nguyên mẫu - prototype chain. null không có nguyên mẫu và nó có vai trò như một liên kết cuối cùng trong prototype chain.

Ví dụ: Chúng ta có thể gọi method toString() của object website như sau:

console.log(website.toString()); // '[object Object]'

Method toString() return về một chuỗi biển thị object website. Theo mặc định, nó trả về [object Object].

Khi hàm là giá trị của thuộc tính trong object thì nó được gọi là method.

Ở ví dụ này, khi chúng ta gọi method toString() bằng object website, JavaScript sẽ thử tìm nó trong object website. Do object chúng ta tạo không có method toString(), nên nó sẽ tiếp tục tìm kiếm method toString() trong đối tượng prototype của object.

example prototype JavaScript

Chúng ta thấy trong prototype của website có method toString(), nên JavaScript sẽ sử dụng toString() của prototype này.


Trong JavaScript có một hàm built-inObject(). Nếu sử dụng toán tử typeof sẽ cho kết quả 'function'.

console.log(typeof Object); // function

Các bạn chú ý là Object() là một hàm, chứ không phải là một object 😥😁.

Ngoài ra, JavaScript tạo ra một anonymous object - object ẩn danh và object này được tham chiếu qua thuộc tính prototype của hàm Object().

Mỗi function sẽ có một prototype object theo mặc định. Thuộc tính prototype của function có thể được truy cập bằng cách sử dụng <tên hàm>.prototype

console.log(Object.prototype);

JavaScript Object.prototype

object Object.prototype có một số method hữu ích như toString()valueOf(). Nó cũng có một thuộc tính quan trọng được gọi là constructor tạo tham chiếu đến hàm Object().

console.log(Object.prototype.constructor === Object); // true

Ví dụ để các bạn hình dung ^^:

Chúng ta sẽ định nghĩa một hàm khởi tạo - constructor function là Student như bên dưới:

function Student(name) {
    this.name = name;
}

Giống như hàm Object(), hàm Student() có một thuộc tính là prototype tham chiếu đến một anonymous object. Và anonymous object có thuộc tính constructor tạo tham chiếu đến hàm Student().

console.log(Student);
console.log(Student.prototype);

example JavaScript Object.prototype

Ngoài ra, JavaScript liên kết object Student.prototype với object Object.prototype thông qua [[Prototype]], đây được gọi là liên kết nguyên mẫu.

Thêm method cho object prototype

Giả sử mình thêm một method sayHi như sau:

function Student(name) {
    this.name = name;
}

Student.prototype.sayHi = function() {
    return "Xin chào, tên mình là " + this.name + " 😁";
}

Tiếp theo ta tạo một đối tượng mới:

const student1 = new Student('Hân');

console.log(student1); // {name: 'Hân'}

Sau đó gọi method sayHi:

student1.sayHi(); // 'Xin chào, tên mình là Hân 😁'

Kết quả ta được như trên, dù sử dụng sayHi từ object student1: {name: 'Hân'} nhưng kết quả vẫn được in ra 🤨. Đó là do khi không tìm thấy method sayHi, JavaScript đã đi theo liên kết nguyên mẫu và tìm thấy nó ở object Student.prototype 😁.

Bây giờ ta thử dùng method toString() xem kết quả thế nào:

student1.toString(); // Kết quả: '[object Object]'

Như bạn thấy ở trên, ta vẫn in được kết quả ra, đó là vì khi không tìm thấy method toString() trong object student1, JavaScript theo liên kết nguyên mẫu và tìm đến Student.prototype, tại đây nó cũng không tìm thấy. Nó tiếp tục theo liên kết nguyên mẫu và tìm đến object Object.prototype. Tại đây nó tìm thấy method toString() và sử dụng method này. Và chúng ta được kết quả như trên 😃😃.

Liên kết giữa student1, Student.prototype, Object.prototype được gọi là prototype chain.

Nếu bạn gọi một method không tồn tại trên student1, object Student.prototype và object Object.prototype, JavaScript thông báo lỗi vì nó không thể tìm thấy method bạn cần.

Ví dụ:

student1.xinNghiPhepHomNay(); // Báo lỗi

Truy xuất liên kết nguyên mẫu

Trong Object.prototype có một thuộc tính gọi là proto. Nó cho ta thấy được liên kết nguyên mẫu trong [[Prototype]] của một object.

proto có thể không được dùng nữa vì nó sẽ được thay thế bằng Object.getPrototypeOf() trong tương lai. Do đó, chúng ta không nên sử dụng proto trong quá trình viết chương trình.

student1.__proto__ trỏ đến object Student.prototype.

console.log(student1.__proto__ === Student.prototype); // true

Như đã đề cập trước đó, bạn nên sử dụng Object.getPrototypeOf() thay vì __proto__.

Object.getPrototypeOf(student1) === Student.prototype // true

Chúng ta có thể xem prototype thông qua contructor của student1:

student1.constructor.prototype

student1.constructor trả về function Student, do đó student1.constructor.prototype trả về object Student.prototype.

Như vậy thông qua bài này, mình xin tóm tắt những kiến thức chúng ta đã học trong bài:

  1. Object Object.prototype có thuộc tính constructor tham chiếu đến hàm Object.
  2. Mọi function đều có một object prototype. Object prototype này tham chiếu đến đối tượng Object.prototype thông qua liên kết [[Prototype]] hay thuộc tính __proto__.
  3. Prototype chain cho phép một object sử dụng các method và thuộc tính của các object prototype của nó thông qua các liên kết [[Prototype]].
  4. Method Object.getPrototypeOf() trả về object prototype của một object. Sử dụng Object.getPrototypeOf() thay vì __proto__.
Có thể bạn thích ⚡
homiedev
About Me

Hi, I'm @devnav. Một người thích chia sẻ kiến thức, đặc biệt là về Frontend 🚀. Trang web này được tạo ra nhằm giúp các bạn học Frontend hiệu quả hơn 🎉😄.

Chúc các bạn tìm được kiến thức hữu ích trong blog này 😁😁.