{...}
Cú pháp thông thường cho phép tạo một đối tượng. Nhưng thường thì chúng ta cần tạo nhiều đối tượng tương tự, như nhiều người dùng hoặc các mục menu, v.v.
Điều đó có thể được thực hiện bằng cách sử dụng các hàm Constructor và toán tử"new"
.
Nội dung chính
1. Hàm Constructor
Hàm Constructor về mặt kỹ thuật là các hàm thông thường. Có hai quy ước:
- Chúng được đặt với tên in hoa chữ đầu tiên.
- Chúng chỉ nên được thực hiện với toán tử
"new"
.
Ví dụ:
/*
Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
@author cafedevn
Contact: cafedevn@gmail.com
Fanpage: https://www.facebook.com/cafedevn
Instagram: https://instagram.com/cafedevn
Twitter: https://twitter.com/CafedeVn
Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
*/
function User(name) {
this.name = name;
this.isAdmin = false;
}
let user = new User("Jack");
alert(user.name); // Jack
alert(user.isAdmin); // false
Khi một hàm được thực thi vớinew
, nó thực hiện các bước sau:
- Một đối tượng trống mới được tạo và gán cho
this
. - Các phần thân hàm được thực thi. Thông thường nó sửa đổi
this
, thêm giá trị mới cho thuộc tính. - Giá trị của
this
được return cho biến user.
Nói cách khác, new User(...)
làm một cái gì đó như:
function User(name) {
// this = {}; (implicitly)
// add properties to this
this.name = name;
this.isAdmin = false;
// return this; (implicitly)
}
Vì vậy, let user = new User("Jack")
cho kết quả tương tự như:
let user = {
name: "Jack",
isAdmin: false
};
Bây giờ nếu chúng ta muốn tạo người dùng khác, chúng ta có thể gọi new User("Ann")
, new User("Alice")
v.v. Ngắn hơn nhiều so với việc sử dụng chữ dài dòng cho mỗi lần tạo và cũng dễ đọc.
Đó là mục đích chính của các constructors – để thực hiện code tạo đối tượng có thể sử dụng lại.
Chúng ta hãy lưu ý một lần nữa – về mặt kỹ thuật, bất kỳ hàm nào cũng có thể được sử dụng như một hàm tạo. Đó là: bất kỳ hàm nào cũng có thể được chạy cùng new
và nó sẽ thực thi thuật toán ở trên. Chữ viết hoa đầu tiên của tên đối tượng đó là một thỏa thuận chung, để chỉ rõ rằng một hàm sẽ được thực hiện new
.
new function() { … }
Nếu chúng ta có nhiều dòng code về việc tạo duy nhất một đối tượng phức tạp, chúng ta có thể gói chúng trong hàm tạo, như thế này:
let user = new function() {
this.name = "John";
this.isAdmin = false;
// ...other code for user creation
// maybe complex logic and statements
// local variables etc
};
Hàm tạo không thể được gọi lại, vì nó không được lưu ở bất kỳ đâu, chỉ cần tạo và gọi. Vì vậy, thủ thuật này nhằm mục đích đóng gói code xây dựng đối tượng ở một nơi duy nhất, mà không sử dụng lại trong tương lai.
2. Kiểm tra constructor: new.target
Công cụ nâng cao
Cú pháp từ phần này hiếm khi được sử dụng, bỏ qua nó trừ khi bạn muốn biết mọi thứ.
Bên trong một hàm, chúng ta có thể kiểm tra xem nó được gọi có new
hoặc không có nó, bằng cách sử dụng một thuộc tính đặc biệt new.target
.
Nó trống khi gọi thông thường và bằng với hàm nếu được gọi với new
:
function User() {
alert(new.target);
}
// without "new":
User(); // undefined
// with "new":
new User(); // function User { ... }
Điều đó có thể được sử dụng bên trong hàm để biết liệu nó có được gọi với new
không.
Chúng ta cũng có thể thực hiện cả hai new
và khi gọi thông thường để làm như vậy, như thế này:
function User(name) {
if (!new.target) { // if you run me without new
return new User(name); // ...I will add new for you
}
this.name = name;
}
let john = User("John"); // redirects call to new User
alert(john.name); // John
Cách tiếp cận này đôi khi được sử dụng trong các thư viện để làm cho cú pháp linh hoạt hơn. Vì vậy, mọi người có thể gọi hàm có hoặc không new
, và nó vẫn hoạt động.
Có lẽ không phải là một điều tốt để sử dụng ở mọi nơi, bởi vì bỏ qua new
làm cho nó ít rõ ràng hơn những gì đang xảy ra. Với new
tất cả chúng ta đều biết rằng đối tượng mới đang được tạo ra.
3. Return từ constructors
Thông thường, các constructors không có một hàmreturn
. Nhiệm vụ của họ là viết tất cả những thứ cần thiết vào this
, và nó tự động return lại kết quả.
Nhưng nếu có một câu lệnh return
, thì quy tắc rất đơn giản:
- Nếu
return
được gọi với một đối tượng, thì đối tượng được trả về thay vìthis
. - Nếu
return
được gọi với một kiểu nguyên thủy, nó bị bỏ qua.
Nói cách khác, return
với một đối tượng trả về đối tượng đó, trong tất cả các trường hợp khác this
được trả về.
Chẳng hạn, ở đây return
ghi đè this
bằng cách trả về một đối tượng:
function BigUser() {
this.name = "John";
return { name: "Godzilla" }; // <-- returns this object
}
alert( new BigUser().name ); // Godzilla, got that object
Và đây là một ví dụ với một sản phẩm trống được return
(hoặc chúng ta có thể đặt kiểu nguyên thủy sau nó, không thành vấn đề):
function SmallUser() {
this.name = "John";
return; // <-- returns this
}
alert( new SmallUser().name ); // John
Thông thường các constructors không có câu lệnh return
. Ở đây chúng ta đề cập đến hành vi đặc biệt với các đối tượng trả lại chủ yếu vì mục đích hoàn chỉnh.
Bỏ dấu ngoặc đơn
Nhân tiện, chúng ta có thể bỏ qua dấu ngoặc đơn sau new
, nếu nó không có đối số:
let user = new User; // <-- no parentheses
// same as
let user = new User();
Việc bỏ dấu ngoặc đơn ở đây không được coi là một phong cách tốt, nhưng cú pháp được đặc tả cho phép.
4. Các phương thức trong constructor
Sử dụng các hàm constructors để tạo các đối tượng mang lại sự linh hoạt cao. Hàm constructor có thể có các tham số xác định cách xây dựng đối tượng và những gì cần đặt trong đó.
Tất nhiên, chúng ta có thể thêm this
vào không chỉ các thuộc tính, mà cả các phương thức.
Chẳng hạn, new User(name)
bên dưới tạo một đối tượng với name
và phương thức đã cho sayHi
:
function User(name) {
this.name = name;
this.sayHi = function() {
alert( "My name is: " + this.name );
};
}
let john = new User("John");
john.sayHi(); // My name is: John
/*
john = {
name: "John",
sayHi: function() { ... }
}
*/
Để tạo các đối tượng phức tạp, có một cú pháp nâng cao hơn, các class , chúng ta sẽ đề cập sau.
5. Tóm lược
- Các hàm Constructor ngắn gọn, các hàm Constructor là các hàm thông thường, nhưng chúng có một thỏa thuận chung để đặt tên chúng bằng chữ in hoa.
- Hàm Constructor chỉ nên được gọi bằng cách sử dụng
new
. Khi gọi như vậy ngụ ý việc tạo ra sản phẩmthis
và trả lại những cái được điền vào đối tượng.
Chúng ta có thể sử dụng các hàm Constructor để tạo nhiều đối tượng tương tự.
JavaScript cung cấp các hàm Constructor cho nhiều đối tượng trong ngôn ngữ được tích hợp sẵn: như Date
ngày tháng, Set
cho các tập hợp và các đối tượng khác mà chúng tôi dự định nghiên cứu.
Trong chương này, chúng tôi chỉ đề cập đến những điều cơ bản về các đối tượng và các Constructor. Chúng rất cần thiết để tìm hiểu thêm về các kiểu dữ liệu và hàm trong các chương tiếp theo.
Sau khi chúng tôi biết điều đó, chúng tôi trở lại các đối tượng và bao quát chúng sâu hơn trong các chương Nguyên mẫu, kế thừa và Lớp.
Full series tự học Javascript từ cơ bản tới nâng cao tại đây nha.
Nếu bạn thấy hay và hữu ích, bạn có thể tham gia các kênh sau của cafedev để nhận được nhiều hơn nữa:
Chào thân ái và quyết thắng!