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.
Nội dung
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
firstName
vàlastName
lần lượt là'Nguyen'
và'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 firstName
và lastName
, 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.
Tham Gia Cộng Đồng Học Lập Trình Thật Dễ!
Nếu bạn quan tâm đến ngành lập trình, và muốn tìm hiểu những kiến thức bổ ích khác, hãy tham gia ngay cộng đồng Học Lập Trình Thật Dễ nhé!