ES6 đã giới thiệu cho chúng ta về Class trong Javascript, nhưng nó vẫn quá là đơn giản để có thể sử dụng cho các ứng dụng phức tạp. Trường của Class [hay còn được gọi là thuộc tính của Class] có mục đích đem đến các constructor đơn giản hơn với các thuộc tính private và static.
Hãy cùng điểm lại về Class trong ES6 trước khi xem qua các ví dụ chi tiết hơn.
Những điều cơ bản về Class trong ES6
Mô hình kế thừa kiểu Prototype có vẻ sẽ gây khó hiểu đối với các lập trình viên đã quen hay hiểu biết nhiều về kế thừa kiểu Class được sử dụng trong các ngôn ngữ như C++, C#, Java hay PHP. Class trong JavaScript tuy chủ yếu đơn thuần là những cú pháp được thiết kế giúp cho mọi thứ dễ hơn, và nó đồng thời giúp cho những người vốn đã quen với khái niệm lập trình hướng đối tượng trở nên quen thuộc hơn.C++, C#, Java hay PHP. Class trong JavaScript tuy chủ yếu đơn thuần là những cú pháp được thiết kế giúp cho mọi thứ dễ hơn, và nó đồng thời giúp cho những người vốn đã quen với khái niệm lập trình hướng đối tượng trở nên quen thuộc hơn.
Class là một template giúp định nghĩa cách hoạt động của các object thuộc class đó. Class
const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
6 sau định nghĩa cho các loài động vật nói chung [tên các class thường được viết hoa chữ cái đầu tiên để giúp phân biệt chúng với các object và các type khác]:class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
}
Việc khai báo class được thực hiện ở strict mode nên ta không cần thiết phải thêm
const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
7.strict mode nên ta không cần thiết phải thêm const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
7.Hàm
const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
8 sẽ chạy khi một object thuộc loại này được tạo và nó có nhiệm vụ định nghĩa các thuộc tính ban đầu cho object đó. const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
9 và class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
0 là các phương thức giúp thêm các chức năng khác cho object.Và giờ object của ta đã có thể được tạo từ Class này thông qua từ khóa
class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
1:const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
Getter and Setter
Các
class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
2 là các phương thức đặc biệt chỉ được dùng để định nghĩa các giá trị cho object. Tương tự, class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
3 là các phương thức đặc biệt chỉ được dùng để trả về các giá trị. Ví dụ:class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
Child/Sub-class
Việc sử dụng một Class được xây dựng trên một Class khác có lẽ là điều thường thấy khi lập trình hướng đối tượng. Nếu ta hầu như chỉ tạo các object về
class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
4, thì việc sử dụng Class const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
6 sẽ quá tổng quát, và lúc nào ta cũng sẽ phải định nghĩa đi định nghĩa lại việc nó có 4 chân [legs] và kêu "woof" [noise] làm mặc định.Class
class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
6 có thể kế thừa tất cả các thuộc tính và phương thức từ class const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
6 sử dụng từ khóa class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
8. Tất cả những thuộc tính và phương thức cụ thể cho class class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
6 có thể được thêm hoặc bớt nếu cần:class Dog extends Animal {
constructor[name] {
// call the Animal constructor
super[name, 4, 'woof'];
this.type = 'dog';
}
// override Animal.speak
speak[to] {
super.speak[];
if [to] console.log[`to ${to}`];
}
}
class Dog extends Animal {
constructor[name] {
// call the Animal constructor
super[name, 4, 'woof'];
this.type = 'dog';
}
// override Animal.speak
speak[to] {
super.speak[];
if [to] console.log[`to ${to}`];
}
}
0 đại diện cho parent class[] và thường được gọi trong hàm const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
8. Ở ví dụ trên, phương thức const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
9 của class class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
6 đã override phương thức tương ứng được định nghĩa ở class const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
6.Giờ ta có thể tạo ra một object instance của class
class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
6:const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
Phương thức Static và Thuộc tính
Định nghĩa một phương thức với từ khóa
class Dog extends Animal {
constructor[name] {
// call the Animal constructor
super[name, 4, 'woof'];
this.type = 'dog';
}
// override Animal.speak
speak[to] {
super.speak[];
if [to] console.log[`to ${to}`];
}
}
6 sẽ giúp cho phương thức của class đó có thể được gọi mà không cần phải khởi tạo một object instance. JavaScript không hỗ trợ các thuộc tính static giống như các ngôn ngữ lập trình khác, nhưng việc thêm các thuộc tính vào khi định nghĩa class [một class cũng đồng thời là một JavaScript object] là điều có thể.Class
class Animal {
constructor[name = 'anonymous', legs = 4, noise = 'nothing'] {
this.type = 'animal';
this.name = name;
this.legs = legs;
this.noise = noise;
}
speak[] {
console.log[`${this.name} says "${this.noise}"`];
}
walk[] {
console.log[`${this.name} walks on ${this.legs} legs`];
}
// setter
set eats[food] {
this.food = food;
}
// getter
get dinner[] {
return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
}
}
const rex = new Animal['Rex', 4, 'woof'];
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
6 có thể được điều chỉnh lưu trữ được số lần mà các object được tạo từ nó:class Dog extends Animal {
constructor[name] {
// call the Animal constructor
super[name, 4, 'woof'];
this.type = 'dog';
// update count of Dog objects
Dog.count++;
}
// override Animal.speak
speak[to] {
super.speak[];
if [to] console.log[`to ${to}`];
}
// return number of dog objects
static get COUNT[] {
return Dog.count;
}
}
// static property [added after class is defined]
Dog.count = 0;
Hàm static getter
class Dog extends Animal {
constructor[name] {
// call the Animal constructor
super[name, 4, 'woof'];
this.type = 'dog';
}
// override Animal.speak
speak[to] {
super.speak[];
if [to] console.log[`to ${to}`];
}
}
8 của class sẽ trả về số lần mà object dog được tạo:console.log[`Dogs defined: ${Dog.COUNT}`]; // Dogs defined: 0
const don = new Dog['Don'];
console.log[`Dogs defined: ${Dog.COUNT}`]; // Dogs defined: 1
const kim = new Dog['Kim'];
console.log[`Dogs defined: ${Dog.COUNT}`]; // Dogs defined: 2
Các trường được mong chờ trong các chuẩn ES tiếp theo
Một trong các đề xuất về trường của class đó là cho phép chúng được khởi tạo ở ngay đầu Class:
class MyClass {
a = 1;
b = 2;
c = 3;
}
Điều này cũng tương tự với việc:
class MyClass {
constructor[] {
this.a = 1;
this.b = 2;
this.c = 3;
}
}
Trường Static của Class
Các trường trong class cho phép thuộc tính static được khai báo ngay bên trong
class Dog extends Animal {
constructor[name] {
// call the Animal constructor
super[name, 4, 'woof'];
this.type = 'dog';
}
// override Animal.speak
speak[to] {
super.speak[];
if [to] console.log[`to ${to}`];
}
}
9. Ví dụ:class MyClass {
x = 1;
y = 2;
static z = 3;
}
console.log[ MyClass.z ]; // 3
Và tương tự trong ES6 ta đã có một cách không gọn ghẽ cho lắm:
const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
0Trường Private của class
Tất cả các thuộc tính trong class của ES6 đều mặc định là public và có thể được xem, chỉnh sửa từ bên ngoài class. Trong ví dụ về class
const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
6 trên, không có gì có thể ngăn cản việc thuộc tính const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
1 có thể sẽ bị thay đổi mà không cần thông qua hàm setter const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
2:const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
1Các ngôn ngữ khác cho phép khai báo thuộc tính
const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
3. Nhưng đó là điều không thể trong ES6, mặc dù các lập trình viên có thể tạm thời giải quyết vấn đề này bằng cách sử dụng underscore convention [const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
4].Trong các chuẩn ES tiếp theo, các trường private của class có thể được định nghĩa sử dụng dấu thăng
const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
5 làm prefix:const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
2Hãy chú ý rằng không có cách nào để định nghĩa các phương thức, hàm getter settter private, mặc dù đang có những đề xuất sử dụng dấu thăng
const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
5 làm tiền tố cho tên. Ví dụ:const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
3Lợi ích: Code React trông gọn gàng hơn
Các component React thường có những phương thức gắn với các sự kiện DOM. Để đảm bảo ngữ cảnh
const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
7 hoạt động đúng cho component hiện tại, việc phải const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
8 tất cả các phương thức tương ứng là cần thiết. VÍ dụ:const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
4Nếu
const rex = new Dog['Rex'];
rex.speak['everyone']; // Rex says "woof" to everyone
rex.eats = 'anything';
console.log[ rex.dinner ]; // Rex eats anything for dinner.
9 được định nghĩa là trường của class, nó có thể được set cho một hàm bằng cách dùng chuẩn arrow class Dog extends Animal {
constructor[name] {
// call the Animal constructor
super[name, 4, 'woof'];
this.type = 'dog';
// update count of Dog objects
Dog.count++;
}
// override Animal.speak
speak[to] {
super.speak[];
if [to] console.log[`to ${to}`];
}
// return number of dog objects
static get COUNT[] {
return Dog.count;
}
}
// static property [added after class is defined]
Dog.count = 0;
0 từ ES6, điều này sẽ giúp nó được bind một cách tự động vào object được định nghĩa. class Dog extends Animal {
constructor[name] {
// call the Animal constructor
super[name, 4, 'woof'];
this.type = 'dog';
// update count of Dog objects
Dog.count++;
}
// override Animal.speak
speak[to] {
super.speak[];
if [to] console.log[`to ${to}`];
}
// return number of dog objects
static get COUNT[] {
return Dog.count;
}
}
// static property [added after class is defined]
Dog.count = 0;
1 cũng có thể được khai báo như một trường của Class nên ta không cần phải có constructor:const rex = new Animal['Rex', 4, 'woof'];
rex.speak[]; // Rex says "woof"
rex.noise = 'growl';
rex.speak[]; // Rex says "growl"
5References
- //www.sitepoint.com/javascript-private-class-fields/
- //www.sitepoint.com/object-oriented-javascript-deep-dive-es6-classes/