FPrototype của hàm trong JavaScript

Trong bài viết về khởi tạo object với new trong JavaScript, bạn biết rằng một object có thể được tạo ra bằng cách sử dụng từ khóa new và hàm khởi tạo, ví dụ:

let obj = new F();

Và đặc biệt, nếu F.prototype là một object thì toán tử new sẽ sử dụng thuộc tính đó để gán cho [[Prototype]] của đối tượng mới.

Chú ý: với F.prototype thì prototype chính là tên của một thuộc tính trong F.

Ví dụ về F.prototype như sau:

let animal = {
  eats: true,
};

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

Rabbit.prototype = animal;

let rabbit = new Rabbit("White Rabbit"); //  rabbit.__proto__ == animal

console.log(rabbit.eats); // true

Trong ví dụ trên, câu lệnh Rabbit.prototype = animal gán giá trị animal cho thuộc tính prototype trong hàm khởi tạo Rabbit.

Điều này có ý nghĩa là: mỗi một đối tượng mới được tạo ra bởi new Rabbit thì đối tượng animal sẽ được gán cho [[Prototype]] của object.

Đặc điểm của F.prototype

F.prototype chỉ được sử dụng tại thời điểm gọi new F(). Khi đó, giá trị prototype của hàm F sẽ được gán cho [[Prototype]] của object mới.

Nếu F.prototype bị thay đổi giá trị thì đối tượng được tạo trước đó vẫn giữ nguyên giá trị [[Prototype]] cũ, ví dụ:

let animal = {
  eats: true,
};

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

Rabbit.prototype = animal;

let rabbit = new Rabbit("White Rabbit"); //  rabbit.__proto__ == animal
console.log(rabbit.eats); // true

// Thay đổi giá trị của Rabbit.prototypeRabbit.prototype = {  legs: 4,};// prototype của đối tượng rabbit vẫn không đổiconsole.log(rabbit.eats); // trueconsole.log(rabbit.legs); // undefined

Giá trị mặc định của prototype trong hàm

Mỗi hàm trong JavaScript đều có thuộc tính prototype kể cả khi bạn không định nghĩa.

Và giá trị mặc định của prototype là một object với một thuộc tính duy nhất constructor trỏ về chính hàm đó, ví dụ:

function Rabbit() {}

/* prototype mặc định
    Rabbit.prototype = { constructor: Rabbit };
    */

console.log(Rabbit.prototype.constructor === Rabbit);

Vì giá trị của Rabbit.prototype sẽ được gán cho [[Prototype]] của mỗi object được tạo ra bởi việc gọi new Rabbit(), nên bạn có thể truy cập vào constructor từ mỗi đối tượng:

function Rabbit() {}
// mặc định:
// Rabbit.prototype = { constructor: Rabbit }

let rabbit = new Rabbit(); // kế thừa prototype từ {constructor: Rabbit}

console.log(rabbit.constructor === Rabbit); // true

Và bạn có thể sử dụng giá trị constructor đó để khởi tạo đối tượng mới như sau:

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

let rabbit = new Rabbit("White Rabbit");
console.log(rabbit.name);

let rabbit2 = new rabbit.constructor("Black Rabbit");
console.log(rabbit2.name);

Tính năng này đặc biệt hữu ích khi bạn không biết hàm khởi tạo của một object (ví dụ đối tượng được tạo ra từ thư viện bên thứ 3).

Chú ý: JavaScript không đảm bảo giá trị chính xác cho constructor. Thực chất, constructor là thuộc tính mặc định của mỗi hàm. Nhưng giá trị của constructor thì hoàn toàn có thể thay đổi được.

Ví dụ thay đổi giá trị của prototype:

function Rabbit() {}
Rabbit.prototype = {
  jumps: true,
};

let rabbit = new Rabbit();
console.log(rabbit.constructor === Rabbit); // false

Trong ví dụ trên, giá trị của prototype được gán bằng một object hoàn toàn mới và không chứa thuộc tính constructor nữa.

Để giữa lại giá trị mặc định của constructor, bạn chỉ cần thêm/bớt thuộc tính, thay vì gán object mới hoàn toàn cho prototype như sau:

function Rabbit() {}

// thay vì ghi đè giá trị của prototype, bạn chỉ thêm thuộc tính mới
Rabbit.prototype.jumps = true;

// giá trị mặc định của Rabbit.prototype.constructor không đổi
console.log(Rabbit.prototype.constructor === Rabbit);

Hoặc chủ động gán lại giá trị cho thuộc tính constructor:

Rabbit.prototype = {
  jumps: true,
  constructor: Rabbit,
};

// prototype được gán bằng object mới,
// nhưng constructor được tạo lại như mặc định

Tổng kết

Sau đây là những kiến thức cơ bản cần nhớ về prototype của hàm trong JavaScript F.prototype:

  • Thuộc tính F.prototype là một thuộc tính mặc định của mỗi hàm trong JavaScript dùng để gán giá trị cho [[Prototype]] trong mỗi object tạo ra từ cách gọi new F().
  • Giá trị của F.prototype chỉ có thể là một object hoặc null, các giá trị khác bị bỏ qua.
  • Thuộc tính prototype chỉ được dùng tại thời điểm gọi new F().

Trong đối tượng thông thường,prototype chỉ đơn giản là một thuộc tính mà không có ý nghĩa gì đặc biệt:

let user = {
  name: "Alex",
  prototype: "abc",
};

Mặc định, mỗi hàm đều có F.prototype = { constructor: F }. Vì vậy, bạn có thể truy cập đến hàm khởi tạo của mỗi object thông qua giá trị của thuộc tính constructor.

Tham khảo: F.prototype

Bài trước
left Bài trước
left Prototype trong JavaScript
Bài tiếp theo
Native Prototype trong JavaScript right
Bài tiếp theo right
Avatar Techmely Team
VIẾT BỞI

Techmely Team