Sử Dụng Constructor Function Trong JavaScript Để Khởi Tạo Object

object trong javascript

Trong bài viết này, mình sẽ giới thiệu constructor function là gì và làm thế nào để sử dụng constructor function để khởi tạo một object trong JavaScript.

1. Giới thiệu JavaScript Constructor Function

Ở bài viết Object Trong JavaScript Và Các Kiến Thức Bạn Cần Phải Nắm Vững, mình đã hướng dẫn chi tiết làm thế nào để tạo một object bằng literal syntax:

let person = {
    firstName: 'Nguyen',
    lastName: 'Hung'
}

Trong thực tế, bạn sẽ thường xuyên gặp trường hợp cần phải tạo nhiều object tương tự object person.

Để làm việc này dễ dàng, bạn có thể sử dụng constructor function như là một cái khuôn, sau đó bạn dùng cái khuôn để tạo ra các object tương tự nhau.

Nói chi tiết hơn, constructor function đơn giản chỉ là một function thông thường với các quy ước sau:

  • Tên của constructor function bắt đầu bằng một kí tự in hoa như Person, Document,…
  • Sử dụng toán tử new khi gọi constructor function.

Lưu ý: Phiên bản ES6 có keyword class và chức năng tương tự như constructor function. Nhưng bản chất của nó vẫn là constructor function.

Ở ví dụ sau, mình sẽ định nghĩa một constructor function Person:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

Để khởi tạo một object (instance) từ Person, mình sử dụng toán tử new:

let person = new Person('Nguyen', 'Hung');

Về cơ bản, toán tử new làm những việc sau đây:

  • Tạo một object rỗng và gán nó vào this.
  • Gán giá trị cho property firstNamelastName lần lượt là 'Nguyen''Hung'.
  • Trả về keyword this.

Mình có thể mô phỏng tương đương như sau:

function Person(firstName, lastName) {
  // this = {};

  // add properties to this
  this.firstName = firstName;
  this.lastName = lastName;

  // return this;
}

Do đó, khi chương trình thực thi câu lệnh:

let person = new Person('Nguyen', 'Hung');

… thì giá trị của person là:

{
    firstName: 'Nguyen',
    lastName: 'Hung'
}

Vì vậy, bạn có thể sử dụng constructor function Person để khởi tạo ra các object tương tự:

let person1 = new Person('Tran', 'Tien');
let person2 = new Person('Cris', 'Ronaldo');

2. Thêm method vào JavaScript constructor function

Để thêm method cho một object thông qua constructor function, bạn có thể sử dụng keyword this. Ví dụ:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  this.getFullName = function () {
    return this.firstName + " " + this.lastName;
  };
}

Bây giờ, bạn có thể khởi tạo object có method getFullName:

let person = new Person('Nguyen', 'Hung');
console.log(person.getFullName());

Output:

'Nguyen Hung'

Tuy nhiên, có một vấn đề là khi bạn khởi tạo nhiều instance của Person thì method this.getFullName() bị trùng lặp ở mỗi instance, gây lãng phí bộ nhớ.

Để giải quyết vấn đề này, bạn có thể sử dụng prototype để tất cả các instance sử dụng chung method từ một nguồn.

3. Gọi constructor function không cần keyword new

Bạn có thể gọi một constructor function không cần keyword new:

let person = Person('Nguyen', 'Hung');

Ở trường hợp này, Person thực thi như một function thông thường. Do đó this bên trong function Person sẽ tham chiếu đến object global.

Nếu bạn cố gắng truy cập property firstNamelastName, thì chương trình sẽ báo lỗi:

console.log(person.firstName);

Error:

TypeError: Cannot read property 'firstName' of undefined

Tương tự như vậy, bạn cũng không thể truy cập method getFullName():

person.getFullName();

Error:

TypeError: Cannot read property 'getFullName' of undefined

Để tránh việc không dùng keyword new khi gọi constructor function thì bạn có thể sử dụng property new.target trong ES6.

Nếu bạn dùng keyword new khi gọi constructor function, thì new.target có giá trị là tham chiếu đến function. Ngược lại giá trị của nó là undefined.

function Person(firstName, lastName) {
    console.log(new.target);

    this.firstName = firstName;
    this.lastName = lastName;

    this.getFullName = function () {
        return this.firstName + " " + this.lastName;
    };
}

let person = new Person('Nguyen', 'Hung');

Output:

undefined

Đoạn code trên new.target có giá trị là undefined, bởi vì Person thực thi như một function thông thường.

Tuy nhiên, ở ví dụ sau đây, new.target có giá trị là tham chiếu đến function Person bởi vì bạn đã sử dụng keyword new để gọi function.

let person = new Person('Nguyen', 'Hung');

Output:

[Function: Person]

Bạn có thể bắt buộc người dùng phải sử dụng keyword new khi gọi constructor function, nếu không chương trình sẽ báo lỗi:

function Person(firstName, lastName) {
    if (!new.target) {
        throw Error("Cannot be called without the new keyword");
    }

    this.firstName = firstName;
    this.lastName = lastName;
}

Ngoài ra, bạn cũng có thể khởi tạo object của Person nếu new.target có giá trị là undefined:

function Person(firstName, lastName) {
    if (!new.target) {
        return new Person(firstName, lastName);
    }

    this.firstName = firstName;
    this.lastName = lastName;
}

let person = Person('Nguyen', 'Hung');

console.log(person.firstName);

Cách này thường được các thư viện hoặc framework của JavaScript sử dụng để giúp việc viết code được linh hoạt hơn.

5 1 vote
Đánh giá
guest
0 Bình luận
Inline Feedbacks
View all comments
0
Nếu bạn có thắc mắc gì hãy để lại bình luận nhé!!!x