Prototype trong Javascript [JAVASCRIPT]


Bài viết trước ta đã tìm hiểu cách tạo object từ constructor function. Hôm nay ta sẽ tìm hiểu prototype là gì ?

Ví dụ ta có một function constructor như sau :

function Person(name, email) {
  this.name = name;
  this.email = email;
}

mỗi lần ta tạo instance thì object sẽ có thuộc tính name và email.

// instance
var object1 = new Person("Mr D", "example1@tuts.net");
console.log(object1);

// {
// name:"Mr D",
// email: "example1@tuts.net"
// <prototype>: {
//   constructor: Person {..}
//   prototype: Object {}
// }
//
// }

Ngoài ra ta có thêm prototype. Prototype dùng để thêm các thuộc tính (property) hoặc phương thức (method) dùng để chia sẽ, dùng chung cho các instance. Mặc định khi ta chưa khai báo thuộc tính hoặc phương thức trong prototype thì như ví dụ trên ta thấy trong prototype này chỉ có 1 constructor function ( object 1 được tạo ra từ constructor có tên là Person) và 1 protoype Object (Cái này mình sẽ nói sau).

Ta có thể kiểm tra instance được tạo ra từ constructor nào.

console.log(object1 instanceof Person); // true

Hoặc có thể truy xuất constructor của instance

console.log(object1.constructor); // function Person

còn muốn truy xuất vào prototype ta có nhiều cách:

console.log(Person.prototype);

// <prototype>: {
//   constructor: Person {..}
//   prototype: Object {}
// }

console.log(object1.constructor.prototype);

// <prototype>: {
//   constructor: Person {..}
//   prototype: Object {}
// }

console.log(Object.getPrototypeOf(object1));

// <prototype>: {
//   constructor: Person {..}
//   prototype: Object {}
// }

console.log(object1.__proto__);

// <prototype>: {
//   constructor: Person {..}
//   prototype: Object {}
// }

Bây giờ ta định nghĩa 1 thuộc tính tên là "pay" dùng chung cho các instance.

Person.prototype.pay = "Cash";

Ta xem lại thuộc tính "pay" đã được thêm vào prototype.

console.log(Person.prototype);

// <prototype>: {
//   constructor: Person {..}
//   pay: "Cash"
//   prototype: Object {}
// 

Ta truy xuất thuộc tính "pay" như sau:

console.log(object1.pay); // Cash

Nếu ta tạo thêm instance khác

var object2 = new Person("Mrs T", "example2@tuts.net");
console.log(object2.pay); // Cash
console.log(object1.pay); // Cash

Ta thấy là cả 2 instance, object1 và object2 đều dùng chung thuộc tính "pay. có giá trị là "Cash".

Nếu ta thay đổi giá trị trong "pay"

Person.prototype.pay = "Check";

console.log(object2.pay); // Check
console.log(object1.pay); // Check

Thì ta thấy cả object1 và object2 đều thay đổi giá trị về "Check".

Nếu ta muốn object2 thuộc tính "pay" là "Cash". Ta có thể override (ghi đè) thuộc tính của prototype.

object2.pay = "Cash";
console.log(object2.pay); // Cash
console.log(object1.pay); // Check

Chỉ có object2 pay là "Cash". Còn các instance khác pay vẫn là "Check".

Vậy nếu muốn kiểm tra thuộc tính nào là của object , thuộc tính nào là của prototype. Ta dùng "hasOwnProperty".

console.log(object1.hasOwnProperty("name")); // true
console.log(object1.hasOwnProperty("pay")); // false

Object1 có thuộc tính "name", thuộc tính "pay" là của prototype.

Vậy còn

console.log(object2.hasOwnProperty("pay")); 

kết qủa sẽ là "true". Tại vì khi

object2.pay = "Cash";

Thì đã tạo thuộc tình tên là "pay". Ta xem log sau:

console.log(object2);

// {
// name:"Mrs T"
// pay: "Cash"
// email: "example2@tuts.net"
// <prototype>: {
//   constructor: Person {..}
//   pay: "Check"
//   prototype: Object {}
// }
//
// }

Ta thấy là thuộc tính "pay" của object sẽ được ưu tiên hơn so với "pay" của prototype.

Tương tự ta có thể tạo phương thức (method) cho prototype.

Person.prototype.run = function(){
  console.log('running');
}

object1.run(); // running
object2.run(); // running

Như vậy ta đã tìm hiểu prototype trong javascript rồi đó.