Trong cuốn sách này, phong cách lập trình hướng đối tượng [OOP] của JavaScript được giới thiệu theo bốn bước. Chương này bao gồm bước 3 và 4, chương trước bao gồm bước 1 và 2. Các bước là [hình. 12]
- Đối tượng đơn lẻ [chương trước]. Làm cách nào để các đối tượng, các khối xây dựng OOP cơ bản của JavaScript, hoạt động độc lập?
- Chuỗi nguyên mẫu [chương trước]. Mỗi đối tượng có một chuỗi không hoặc nhiều đối tượng nguyên mẫu. Nguyên mẫu là cơ chế kế thừa cốt lõi của JavaScript
- Lớp học [chương này]. Các lớp của JavaScript là nhà máy cho các đối tượng. Mối quan hệ giữa một lớp và các thể hiện của nó dựa trên sự kế thừa nguyên mẫu [bước 2]
- Phân lớp [chương này]. Mối quan hệ giữa lớp con và lớp cha của nó cũng dựa trên sự kế thừa nguyên mẫu
29. 1 Tờ ăn gian. các lớp học
siêu lớp
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
const tarzan = new Person['Tarzan'];
assert.equal[
tarzan.describe[],
'Person named Tarzan'
];
assert.deepEqual[
Person.extractNames[[tarzan, new Person['Cheeta']]],
['Tarzan', 'Cheeta']
];
phân lớp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
ghi chú
13 là trường riêng và phải được khai báo [dòng A] trước khi có thể khởi tạo [dòng B]class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Một trường riêng tư chỉ có thể được truy cập bên trong lớp xung quanh nó. Nó thậm chí không thể được truy cập bởi các lớp con
14 là một thuộc tính và có thể được khởi tạo mà không cần khai báo trước [dòng C]. JavaScript tương đối thường công khai dữ liệu cá thể [ngược lại với e. g. , Java thích ẩn nó hơn]class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
29. 2 Các yếu tố cần thiết của lớp học
Các lớp về cơ bản là một cú pháp nhỏ gọn để thiết lập các chuỗi nguyên mẫu [đã được giải thích trong chương trước]. Về cơ bản, các lớp của JavaScript là độc đáo. Nhưng đó là điều mà chúng tôi ít thấy khi làm việc với họ. Họ thường cảm thấy quen thuộc với những người đã sử dụng các ngôn ngữ lập trình hướng đối tượng khác
Lưu ý rằng chúng ta không cần các lớp để tạo các đối tượng. Chúng tôi cũng có thể làm như vậy thông qua đối tượng chữ. Đó là lý do tại sao mẫu đơn không cần thiết trong JavaScript và các lớp được sử dụng ít hơn so với nhiều ngôn ngữ khác có chúng
29. 2. Hạng 1 A dành cho người
Trước đây chúng tôi đã làm việc với
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
16, các đối tượng đơn lẻ đại diện cho người. Hãy sử dụng một khai báo lớp để triển khai một nhà máy cho các đối tượng đóclass Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
16 hiện có thể được tạo thông qua class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
19class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0Hãy kiểm tra những gì bên trong cơ thể của lớp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20
21 là một phương thức đặc biệt được gọi sau khi tạo một thể hiện mới. Bên trong nó,class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
22 đề cập đến trường hợp đóclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
[ES2022]
13 là trường riêng của một cá thể. Các trường như vậy được lưu trữ trong các trường hợp. Chúng được truy cập tương tự như các thuộc tính, nhưng tên của chúng là riêng biệt – chúng luôn bắt đầu bằng các ký hiệu băm [class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
24]. Và họ vô hình với thế giới bên ngoài lớp họcclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
6class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
Trước khi chúng ta có thể khởi tạo
13 trong hàm tạo [dòng B], chúng ta cần khai báo nó bằng cách đề cập đến nó trong phần thân của lớp [dòng A]class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
26 là một phương thức. Nếu chúng ta gọi nó thông quaclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
27 thìclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
22 đề cập đếnclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
29 bên trong cơ thể củaclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
26class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
3class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
31 là một phương thức tĩnh. "Tĩnh" có nghĩa là nó thuộc về lớp, không thuộc về thể hiệnclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
5class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
Chúng ta cũng có thể tạo các thuộc tính thể hiện [trường công khai] trong hàm tạo
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6Ngược lại với các trường riêng của cá thể, các thuộc tính của cá thể không cần phải khai báo trong thân lớp
29. 2. 2 Biểu thức lớp
Có hai loại định nghĩa lớp [cách định nghĩa lớp]
- Khai báo lớp, mà chúng ta đã thấy trong phần trước
- Biểu thức lớp, mà chúng ta sẽ thấy tiếp theo
Các biểu thức lớp có thể ẩn danh và được đặt tên
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
7Tên của biểu thức lớp được đặt tên hoạt động tương tự như tên của biểu thức hàm được đặt tên. Nó chỉ có thể được truy cập bên trong phần thân của một lớp và giữ nguyên, bất kể lớp đó được gán cho cái gì
29. 2. 3 Nhà điều hành class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
32
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Toán tử
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
32 cho chúng ta biết nếu một giá trị là một thể hiện của một lớp nhất địnhclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0Chúng ta sẽ khám phá toán tử
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
32 chi tiết hơn sau, sau khi chúng ta xem xét phân lớp29. 2. 4 Vị trí công cộng [thuộc tính] so với. khe riêng
Trong ngôn ngữ JavaScript, các đối tượng có thể có hai loại “khe”
- Các vị trí công khai [còn được gọi là thuộc tính]. Ví dụ: các phương thức là các vị trí công khai
- Vị trí riêng tư [ES2022]. Ví dụ: các trường riêng tư là các vị trí riêng tư
Đây là những quy tắc quan trọng nhất mà chúng ta cần biết về thuộc tính và vị trí riêng tư
- Trong các lớp, chúng ta có thể sử dụng các phiên bản công khai và riêng tư của các trường, phương thức, getters và setters. Tất cả chúng đều là các khe trong các đối tượng. Chúng được đặt trong đối tượng nào tùy thuộc vào việc từ khóa
35 có được sử dụng hay không và các yếu tố khácclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Một getter và một setter có cùng khóa sẽ tạo một khe truy cập duy nhất. Một Accessor cũng có thể chỉ có một getter hoặc chỉ một setter
- Thuộc tính và vị trí riêng tư rất khác nhau – ví dụ
Thông tin thêm về thuộc tính và vị trí riêng tư
Chương này không đề cập đến tất cả các chi tiết về tài sản và vị trí riêng tư [chỉ những điều cần thiết]. Nếu bạn muốn tìm hiểu sâu hơn, bạn có thể làm như vậy tại đây
Lớp sau minh họa hai loại vị trí. Mỗi trường hợp của nó có một trường riêng và một thuộc tính
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0Đúng như dự đoán, bên ngoài
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
36, chúng tôi chỉ có thể nhìn thấy tài sảnclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
1Tiếp theo, chúng ta sẽ xem xét một số chi tiết về các vị trí riêng tư
29. 2. Chi tiết hơn về các vị trí 5 Private [ES2022] [nâng cao]
29. 2. 5. 1 Không thể truy cập các vị trí riêng tư trong các lớp conMột khe riêng thực sự chỉ có thể được truy cập bên trong phần thân của lớp của nó. Chúng tôi thậm chí không thể truy cập nó từ một lớp con
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
2Subclassing via
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
37 is explained later in this chapter. How to work around this limitation is explained in §29. 5. 4 “Simulating protected visibility and friend visibility via WeakMaps”29. 2. 5. 2 Each private slot has a unique key [a private name]Các khe riêng có các phím duy nhất tương tự như các biểu tượng. Consider the following class from earlier
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
3Internally, the private field of
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
36 is handled roughly like thisclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
4The value of
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
39 is called a private name. We can’t use private names directly in JavaScript, we can only use them indirectly, via the fixed identifiers of private fields, private methods, and private accessors. Where the fixed identifiers of public slots [such as class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
40] are interpreted as string keys, the fixed identifiers of private slots [such as class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
41] refer to private names [similarly to how variable names refer to values]29. 2. 5. 3 The same private identifier refers to different private names in different classesBecause the identifiers of private slots aren’t used as keys, using the same identifier in different classes produces different slots [line A and line C]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
529. 2. 5. 4 The names of private fields never clashEven if a subclass uses the same name for a private field, the two names never clash because they refer to private names [which are always unique]. In the following example,
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
42 in class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
43 does not clash with class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
42 in class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
45, even though both slots are stored directly in class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
46class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6Subclassing via
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
37 is explained later in this chapter29. 2. 5. 5 Sử dụng class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
48 để kiểm tra xem một đối tượng có một vị trí riêng khôngThe
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
48 operator can be used to check if a private slot exists [line A]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
7Hãy xem thêm các ví dụ về
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
48 được áp dụng cho các vị trí riêng tưphương pháp riêng tư. Đoạn mã sau cho thấy các phương thức riêng tư tạo các vị trí riêng tư trong các phiên bản
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
8Trường riêng tĩnh. Chúng tôi cũng có thể sử dụng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
48 cho trường riêng tĩnhclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
9Phương thức riêng tư tĩnh. Và chúng ta có thể kiểm tra vị trí của một phương thức riêng tư tĩnh
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
0Sử dụng cùng một định danh riêng trong các lớp khác nhau. Trong ví dụ tiếp theo, hai lớp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
52 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20 đều có một vị trí có mã định danh là class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
54. Toán tử class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
48 phân biệt chúng một cách chính xácclass Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
129. 2. 6 Ưu nhược điểm của class trong JavaScript
Tôi khuyên bạn nên sử dụng các lớp vì những lý do sau
Các lớp là một tiêu chuẩn chung để tạo và kế thừa đối tượng hiện được hỗ trợ rộng rãi trên các thư viện và khung. Đây là một cải tiến so với trước đây, khi hầu hết mọi framework đều có thư viện kế thừa riêng
Họ trợ giúp các công cụ như IDE và trình kiểm tra loại trong công việc của họ và kích hoạt các tính năng mới ở đó
Nếu bạn đến từ một ngôn ngữ khác với JavaScript và đã quen với các lớp học, thì bạn có thể bắt đầu nhanh hơn
Công cụ JavaScript tối ưu hóa chúng. Nghĩa là, mã sử dụng các lớp hầu như luôn nhanh hơn mã sử dụng thư viện kế thừa tùy chỉnh
Chúng ta có thể phân lớp các hàm dựng sẵn như
56class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
Điều đó không có nghĩa là các lớp học là hoàn hảo
Có nguy cơ lạm dụng quyền thừa kế
Có nguy cơ đưa quá nhiều chức năng vào các lớp [khi một số chức năng thường được đưa vào các chức năng tốt hơn]
Các lớp trông quen thuộc với các lập trình viên đến từ các ngôn ngữ khác, nhưng chúng hoạt động khác và được sử dụng khác [xem tiểu mục tiếp theo]. Do đó, có nguy cơ những lập trình viên viết mã không giống như JavaScript
Cách các lớp dường như hoạt động bề ngoài hoàn toàn khác với cách chúng thực sự hoạt động. Nói cách khác, có sự mất kết nối giữa cú pháp và ngữ nghĩa. Hai ví dụ là
- Một định nghĩa phương thức bên trong một lớp
57 tạo một phương thức trong đối tượngclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
58class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Các lớp là các chức năng
Động lực cho việc ngắt kết nối là khả năng tương thích ngược. Rất may, việc ngắt kết nối gây ra một số vấn đề trong thực tế;
- Một định nghĩa phương thức bên trong một lớp
Đây là cái nhìn đầu tiên về các lớp học. Chúng tôi sẽ sớm khám phá nhiều tính năng hơn
Tập thể dục. Viết một lớp học
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
5929. 2. 7 Mẹo sử dụng lớp học
- Sử dụng tính kế thừa một cách tiết kiệm – nó có xu hướng làm cho mã phức tạp hơn và trải rộng các chức năng liên quan trên nhiều vị trí
- Thay vì các thành viên tĩnh, tốt hơn là sử dụng các hàm và biến bên ngoài. Chúng tôi thậm chí có thể đặt những thứ đó ở chế độ riêng tư thành một mô-đun, đơn giản bằng cách không xuất chúng. Hai ngoại lệ quan trọng đối với quy tắc này là
- Chỉ đặt chức năng cốt lõi trong các phương thức nguyên mẫu. Các chức năng khác được triển khai tốt hơn thông qua các hàm - đặc biệt là các thuật toán liên quan đến các thể hiện của nhiều lớp
29. 3 Nội bộ của các lớp
29. 3. Lớp 1 A thực sự là hai đối tượng được kết nối
Về cơ bản, một lớp trở thành hai đối tượng được kết nối. Hãy xem lại lớp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20 để xem nó hoạt động như thế nàoclass Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
2Đối tượng đầu tiên được tạo bởi lớp được lưu trữ trong
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20. Nó có bốn thuộc tínhclass Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
3Hai tài sản còn lại là
62 là phương thức tĩnh mà chúng ta đã thấy trong thực tếclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
63 trỏ đến đối tượng thứ hai được tạo bởi một định nghĩa lớpclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
Đây là nội dung của
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
63class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
4Có hai thuộc tính
65 trỏ đến hàm tạoclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
66 là phương pháp mà chúng tôi đã sử dụngclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
29. 3. 2 Các lớp thiết lập chuỗi nguyên mẫu cho các phiên bản của chúng
Đối tượng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
63 là nguyên mẫu của tất cả các phiên bảnclass Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
5Điều đó giải thích cách các cá thể nhận được các phương thức của chúng. Họ kế thừa chúng từ đối tượng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
63Quả sung. 13 hình dung cách mọi thứ được kết nối
Hình 13. Lớpclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20 có thuộc tính class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
70 trỏ đến một đối tượng là nguyên mẫu của tất cả các phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20. Các đối tượng class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
16 là hai trường hợp như vậy29. 3. 3 ____174 so với. class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
70
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Rất dễ nhầm lẫn giữa
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
74 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
70. Hy vọng, hình. 13 nói rõ chúng khác nhau như thế nào
74 là một bộ truy cập của lớpclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
79 cho phép chúng tôi lấy và đặt các nguyên mẫu của các thể hiện của nóclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
70 là một tài sản bình thường như bao tài sản khác. Nó chỉ đặc biệt vì toán tửclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
81 sử dụng giá trị của nó làm nguyên mẫu của các thể hiện. Tên của nó không phải là lý tưởng. Một tên khác chẳng hạn nhưclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
82 sẽ phù hợp hơnclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
29. 3. 4 class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
65 [nâng cao]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Có một chi tiết trong hình. 13 mà chúng tôi chưa xem xét.
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
65 điểm trở lại class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
6Thiết lập này tồn tại do khả năng tương thích ngược. Nhưng nó có hai lợi ích bổ sung
Đầu tiên, mỗi thể hiện của một lớp kế thừa thuộc tính
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
86. Do đó, với một ví dụ, chúng ta có thể tạo các đối tượng “tương tự” thông qua nóclass Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
7Thứ hai, chúng ta có thể lấy tên của lớp đã tạo một thể hiện nhất định
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
829. 3. 5 Đã gửi so với. gọi phương thức trực tiếp [nâng cao]
Trong tiểu mục này, chúng ta tìm hiểu về hai cách gọi phương thức khác nhau.
- Các cuộc gọi phương thức đã gửi
- Gọi phương thức trực tiếp
Hiểu cả hai sẽ cho chúng ta những hiểu biết quan trọng về cách thức hoạt động của các phương pháp
Chúng ta cũng sẽ cần đến cách thứ hai ở phần sau của chương này. Nó sẽ cho phép chúng tôi mượn các phương pháp hữu ích từ
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
8729. 3. 5. 1 Các lệnh gọi phương thức đã gửiHãy kiểm tra cách gọi phương thức hoạt động với các lớp. Chúng tôi đang xem lại
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15 từ trước đóclass Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
9Quả sung. 14 có sơ đồ với chuỗi nguyên mẫu của
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15Hình 14. Chuỗi nguyên mẫu của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15 bắt đầu với class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15 và tiếp tục với class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
63Các cuộc gọi phương thức bình thường được gửi đi - cuộc gọi phương thức
xảy ra trong hai bước
Gửi đi. JavaScript đi qua chuỗi nguyên mẫu bắt đầu bằng
15 để tìm đối tượng đầu tiên có thuộc tính riêng với khóaclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
94. Đầu tiên, nó xem xétclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
15 và không tìm thấy tài sản riêngclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
96. Nó tiếp tục với nguyên mẫu củaclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
15,class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
63 và tìm một thuộc tính riêng củaclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
99 có giá trị mà nó trả vềclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
Lời kêu gọi. Gọi phương thức một giá trị khác với gọi hàm một giá trị ở chỗ nó không chỉ gọi những gì xuất hiện trước dấu ngoặc đơn với các đối số bên trong dấu ngoặc đơn mà còn đặt
22 cho người nhận lệnh gọi phương thức [trong trường hợp này làclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
15]class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
Cách tự động tìm kiếm một phương thức và gọi nó được gọi là công văn động
29. 3. 5. 2 Các cuộc gọi phương thức trực tiếpChúng tôi cũng có thể thực hiện cuộc gọi phương thức trực tiếp mà không cần gửi
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
00Lần này, chúng tôi trực tiếp trỏ đến phương thức thông qua
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
66 và không tìm kiếm nó trong chuỗi nguyên mẫu. Chúng tôi cũng chỉ định khác nhau cho class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 – thông qua class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
04class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 luôn trỏ đến ví dụBất kể phương thức nằm ở đâu trong chuỗi nguyên mẫu của một thể hiện, thì
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 luôn trỏ đến thể hiện đó [phần đầu của chuỗi nguyên mẫu]. Điều đó cho phép class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
26 truy cập class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
13 trong ví dụKhi nào các cuộc gọi phương thức trực tiếp hữu ích?
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0129. 3. 6 Lớp phát triển từ chức năng thông thường [nâng cao]
Trước ECMAScript 6, JavaScript không có lớp. Thay vào đó, các hàm thông thường được sử dụng làm hàm tạo
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
02Các lớp cung cấp cú pháp tốt hơn cho phương pháp này
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
03Phân lớp đặc biệt phức tạp với các hàm xây dựng. Các lớp học cũng cung cấp các lợi ích vượt xa cú pháp thuận tiện hơn
- Các hàm xây dựng tích hợp như
56 có thể được phân lớpclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Chúng tôi có thể truy cập các thuộc tính bị ghi đè thông qua
10class Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
- Các lớp không thể được gọi theo hàm
- Các phương thức không thể được gọi là
81 và không có thuộc tínhclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
70class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Hỗ trợ dữ liệu phiên bản riêng tư
- Và nhiều hơn nữa
Các lớp tương thích với các hàm xây dựng đến mức chúng thậm chí có thể mở rộng chúng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
04class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
37 và phân lớp được giải thích sau trong chương này29. 3. 6. Lớp 1 A là hàm tạoĐiều này đưa chúng ta đến một cái nhìn sâu sắc thú vị. Một mặt,
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
14 đề cập đến hàm tạo của nó thông qua class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
15Mặt khác, lớp là hàm tạo [một hàm]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
05Hàm tạo [hàm] so với. các lớp học
Do chúng giống nhau như thế nào, tôi sử dụng thuật ngữ hàm tạo [hàm] và lớp thay thế cho nhau
29. 4 Thành viên nguyên mẫu của các lớp
29. 4. 1 Các phương thức và trình truy cập nguyên mẫu công khai
Tất cả các thành viên trong phần thân của khai báo lớp sau tạo các thuộc tính của
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
16class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0629. 4. 1. 1 Tất cả các loại phương thức và trình truy cập nguyên mẫu công khai [nâng cao]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
07Các khóa được trích dẫn và tính toán cũng có thể được sử dụng theo nghĩa đen của đối tượng
Thông tin thêm về bộ truy cập [được xác định thông qua getters và/hoặc setters], trình tạo, phương thức không đồng bộ và phương thức tạo không đồng bộ
29. 4. 2 Các phương thức và trình truy cập riêng tư [ES2022]
Các phương thức riêng tư [và trình truy cập] là sự kết hợp thú vị giữa các thành viên nguyên mẫu và thành viên cá thể
Một mặt, các phương thức riêng tư được lưu trữ trong các vị trí trong phiên bản [dòng A]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
08Tại sao chúng không được lưu trữ trong các đối tượng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
70? Mặt khác, các phương thức riêng tư được chia sẻ giữa các phiên bản - như các phương thức công khai nguyên mẫu
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
09Do đó và do cú pháp của chúng tương tự như các phương thức công khai nguyên mẫu, chúng được đề cập ở đây
Đoạn mã sau minh họa cách hoạt động của các phương thức và trình truy cập riêng tư
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6029. 4. 2. 1 Tất cả các loại phương thức và trình truy cập riêng tư [nâng cao]Với các vị trí riêng tư, các khóa luôn là số nhận dạng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
61Thông tin thêm về bộ truy cập [được xác định thông qua getters và/hoặc setters], trình tạo, phương thức không đồng bộ và phương thức tạo không đồng bộ
29. 5 Thành viên thực thể của các lớp [ES2022]
29. 5. Trường công khai 1 Instance
Các thể hiện của lớp sau có hai thuộc tính thể hiện [được tạo ở dòng A và dòng B]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
62Nếu chúng ta tạo một thuộc tính thể hiện bên trong hàm tạo [dòng B], chúng ta không cần phải “khai báo” nó ở nơi khác. Như chúng ta đã thấy, điều đó khác với các trường riêng chẳng hạn
Lưu ý rằng các thuộc tính thể hiện tương đối phổ biến trong JavaScript; . g. , Java, trong đó hầu hết trạng thái cá thể là riêng tư
29. 5. 1. 1 Các trường công khai của phiên bản với các khóa được trích dẫn và tính toán [nâng cao]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6329. 5. 1. 2 Giá trị của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 trong các trường công khai thể hiện là bao nhiêu? Trong trình khởi tạo của trường công khai phiên bản,
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 đề cập đến phiên bản mới được tạoclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6429. 5. 1. 3 When are instance public fields executed? [advanced]The execution of instance public fields roughly follows these two rules
- Trong các lớp cơ sở [các lớp không có siêu lớp], các trường công khai của cá thể được thực thi ngay trước hàm tạo
- Trong các lớp dẫn xuất [các lớp có siêu lớp]
- Lớp cha thiết lập các vị trí phiên bản của nó khi
20 được gọiclass Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
- Các trường công khai của cá thể được thực thi ngay sau
20class Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
- Lớp cha thiết lập các vị trí phiên bản của nó khi
Ví dụ sau minh họa các quy tắc này
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
65class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
37 và phân lớp được giải thích sau trong chương này29. 5. Trường riêng 2 Instance
Lớp sau chứa hai trường riêng [dòng A và dòng B]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
66Lưu ý rằng chúng ta chỉ có thể sử dụng
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
23 trong dòng C nếu chúng ta khai báo nó trong phần thân của lớp29. 5. 3 Dữ liệu phiên bản riêng tư trước ES2022 [nâng cao]
In this section, we look at two techniques for keeping instance data private. Because they don’t rely on classes, we can also use them for objects that were created in other ways – e. g. , via object literals
29. 5. 3. 1 Before ES6. private members via naming conventionsThe first technique makes a property private by prefixing its name with an underscore. This doesn’t protect the property in any way; it merely signals to the outside. “You don’t need to know about this property. ”
In the following code, the properties
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
24 and class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
25 are privateclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
67With this technique, we don’t get any protection and private names can clash. On the plus side, it is easy to use
Private methods work similarly. They are normal methods whose names start with underscores
29. 5. 3. 2 ES6 and later. private instance data via WeakMapsWe can also manage private instance data via WeakMaps
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
68How exactly that works is explained in the chapter on WeakMaps
This technique offers us considerable protection from outside access and there can’t be any name clashes. But it is also more complicated to use
We control the visibility of the pseudo-property
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
26 by controlling who has access to it – for example. If the variable exists inside a module and isn’t exported, everyone inside the module and no one outside the module can access it. In other words. The scope of privacy isn’t the class in this case, it’s the module. We could narrow the scope, thoughclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
69This technique doesn’t really support private methods. But module-local functions that have access to
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
26 are the next best thingclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
30Note that
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 becomes the explicit function parameter class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
29 [line A]29. 5. 4 Simulating protected visibility and friend visibility via WeakMaps [advanced]
As previously discussed, instance private fields are only visible inside their classes and not even in subclasses. Thus, there is no built-in way to get
- Protected visibility. A class and all of its subclasses can access a piece instance data
- Friend visibility. A class and its “friends” [designated functions, objects, or classes] can access a piece of instance data
In the previous subsection, we simulated “module visibility” [everyone inside a module has access to a piece of instance data] via WeakMaps. Therefore
- If we put a class and its subclasses into the same module, we get protected visibility
- If we put a class and its friends into the same module, we get friend visibility
The next example demonstrates protected visibility
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
31Subclassing via
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
37 is explained later in this chapter29. 6 Static members of classes
29. 6. 1 Static public methods and accessors
All members in the body of the following class declaration create so-called static properties – properties of
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
31 itselfclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
3229. 6. 1. 1 All kinds of static public methods and accessors [advanced]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
33Các khóa được trích dẫn và tính toán cũng có thể được sử dụng theo nghĩa đen của đối tượng
Thông tin thêm về bộ truy cập [được xác định thông qua getters và/hoặc setters], trình tạo, phương thức không đồng bộ và phương thức tạo không đồng bộ
29. 6. 2 Static public fields [ES2022]
The following code demonstrates static public fields.
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
32 has three of themclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
3429. 6. 3 Static private methods, accessors, and fields [ES2022]
The following class has two static private slots [line A and line B]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
35This is a complete list of all kinds of static private slots
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
3629. 6. 4 Static initialization blocks in classes [ES2022]
To set up instance data via classes, we have two constructs
- Fields, to create and optionally initialize instance data
- Constructors, blocks of code that are executed every time a new instance is created
For static data, we have
- Static fields
- Static blocks that are executed when a class is created
The following code demonstrates static blocks [line A]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
37We could also execute the code inside the static block after the class [at the top level]. However, using a static block has two benefits
- All class-related code is inside the class
- The code in a static block has access to private slots
The rules for how static initialization blocks work, are relatively simple
- There can be more than one static block per class
- The execution of static blocks is interleaved with the execution of static field initializers
- The static members of a superclass are executed before the static members of a subclass
The following code demonstrates these rules
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
38Subclassing via
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
37 is explained later in this chapter29. 6. 5 Pitfall. Using class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 to access static private fields
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
In static public members, we can access static public slots via
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22. Alas, we should not use it to access static private slots29. 6. 5. 1 class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 and static public fieldsConsider the following code
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
39Subclassing via
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
37 is explained later in this chapterStatic public fields are properties. If we make the method call
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
50then
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 points to class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
43 and everything works as expected. We can also invoke class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
40 via the subclassclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
51class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
45 inherits class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
40 from its prototype class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
43. class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 points to class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
45 and things continue to work, because class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
45 also inherits the property class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
47As an aside, if we assigned to
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
48 in class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
49 and invoked it via class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
50, then we would create a new own poperty of class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
45 that [non-destructively] overrides the property inherited from class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
4329. 6. 5. 2 class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 and static private fieldsConsider the following code
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
52Invoking
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
54 via class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
43 works, because class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 points to class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
43class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
53However, invoking
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
54 via class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
45 does not work, because class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 now points to class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
45 and class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
45 has no static private field class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
63 [private slots in prototype chains are not inherited]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
54The workaround is to accesss
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
63 directly, via class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
43class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
55With static private methods, we are facing the same issue
29. 6. 6 All members [static, prototype, instance] can access all private members
Mọi thành viên trong một lớp có thể truy cập tất cả các thành viên khác trong lớp đó - cả công khai và riêng tư
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
56In contrast, no one outside can access the private members
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
5729. 6. 7 Static private methods and data before ES2022
Đoạn mã sau chỉ hoạt động trong ES2022 – do mỗi dòng có ký hiệu băm [
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
24] trong đóclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
58Since private slots only exist once per class, we can move
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
67 and class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
68 to the scope surrounding the class and use a module to hide them from the world outside the moduleclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
5929. 6. 8 Phương pháp nhà máy tĩnh
Đôi khi có nhiều cách để khởi tạo một lớp. Sau đó, chúng ta có thể triển khai các phương thức tĩnh của nhà máy, chẳng hạn như
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
69class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
60Tôi thích cách mô tả các phương thức nhà máy tĩnh.
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
70 describes how an instance is created. JavaScript’s standard library also has such factory methods – for example
71class Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
72class Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
I prefer to either have no static factory methods or only static factory methods. Things to consider in the latter case
- One factory method will probably directly call the constructor [but have a descriptive name]
- We need to find a way to prevent the constructor being called from outside
In the following code, we use a secret token [line A] to prevent the constructor being called from outside the current module
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6129. 7 Subclassing
Classes can also extend existing classes. For example, the following class
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
73 extends class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
62Terminology related to extending
- Another word for extending is subclassing
20 is the superclass ofclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
73class Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
73 is the subclass ofclass Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
20class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- A base class is a class that has no superclasses
- A derived class is a class that has a superclass
Inside the
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
21 of a derived class, we must call the super-constructor via class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
20 before we can access class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22. Why is that?Let’s consider a chain of classes
- Base class
82class Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
- Class
83 extendsclass Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
82class Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
- Class
57 extendsclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
83class Person { #firstName; // [A] constructor[firstName] { this.#firstName = firstName; // [B] } describe[] { return `Person named ${this.#firstName}`; } static extractNames[persons] { return persons.map[person => person.#firstName]; } }
If we invoke
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
87, class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
57’s constructor super-calls class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
83’s constructor which super-calls class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
82’s constructor. Instances are always created in base classes, before the constructors of subclasses add their slots. Therefore, the instance doesn’t exist before we call class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
20 and we can’t access it via class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22, yetNote that static public slots are inherited. For example,
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
73 inherits the static method class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
94class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
63Exercise. Subclassing
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
9529. 7. 1 The internals of subclassing [advanced]
Figure 15. These are the objects that make up classclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20 and its subclass, class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
73. The left column is about classes. The right column is about the class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
73 instance class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15 and its prototype chainThe classes
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20 and class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
73 from the previous section are made up of several objects [fig. 15]. One key insight for understanding how these objects are related is that there are two prototype chains- The instance prototype chain, on the right
- The class prototype chain, on the left
Chuỗi nguyên mẫu phiên bản bắt đầu với
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
15 và tiếp tục với class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
003 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
63. In principle, the prototype chain ends at this point, but we get one more object. class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87. This prototype provides services to virtually all objects, which is why it is included here, tooclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6429. 7. 1. 2 Chuỗi nguyên mẫu lớp [cột bên trái]Trong chuỗi nguyên mẫu lớp,
class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
73 đến trước, class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20 tiếp theo. Sau đó, chuỗi tiếp tục với class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
008, chỉ ở đó vì class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
20 là một chức năng và các chức năng này cần các dịch vụ của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
008class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6529. 7. 2 class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
32 và phân lớp [nâng cao]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Chúng tôi vẫn chưa biết cách thức hoạt động của
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
32. Làm cách nào để class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
32 xác định xem giá trị class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
014 có phải là một thể hiện của lớp class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
57 hay không [nó có thể là một thể hiện trực tiếp của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
57 hoặc một thể hiện trực tiếp của một lớp con của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
57]? . Đó là, hai biểu thức sau đây là tương đươngclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
66Nếu chúng ta quay trở lại hình. 15, chúng tôi có thể xác nhận rằng chuỗi nguyên mẫu đưa chúng tôi đến các câu trả lời đúng sau đây
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
67Lưu ý rằng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
32 luôn trả về class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
021 nếu phía bên tay của nó là một giá trị nguyên thủyclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
6829. 7. 3 Không phải tất cả các đối tượng đều là phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79 [nâng cao]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Một đối tượng [giá trị không nguyên thủy] chỉ là một thể hiện của
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79 nếu class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 nằm trong chuỗi nguyên mẫu của nó [xem tiểu mục trước]. Hầu như tất cả các đối tượng là thể hiện của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79 – ví dụclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
69Trong ví dụ tiếp theo,
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
026 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
027 đều là đối tượng [dòng A và dòng C], nhưng chúng không phải là thể hiện của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79 [dòng B và dòng D]. class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 không có trong chuỗi nguyên mẫu của họ vì họ không có bất kỳ nguyên mẫu nàoclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
70class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 là đối tượng kết thúc hầu hết các chuỗi nguyên mẫu. Nguyên mẫu của nó là class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
031, có nghĩa là nó cũng không phải là phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
7129. 7. 4 Chuỗi nguyên mẫu của các đối tượng tích hợp [nâng cao]
Tiếp theo, chúng ta sẽ sử dụng kiến thức về phân lớp để hiểu chuỗi nguyên mẫu của một vài đối tượng tích hợp. Chức năng công cụ sau đây
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
033 giúp chúng tôi khám pháclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
72Chúng tôi đã trích xuất phương thức
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
034 của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79 và gán nó cho class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
03629. 7. 4. 1 Chuỗi nguyên mẫu của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
037Hãy bắt đầu bằng cách kiểm tra các đối tượng đơn giản
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
73Hình 16. Chuỗi nguyên mẫu của một đối tượng được tạo thông qua một đối tượng theo nghĩa đen bắt đầu bằng đối tượng đó, tiếp tục với class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 và kết thúc bằng class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
031Quả sung. 16 hiển thị sơ đồ cho chuỗi nguyên mẫu này. Chúng ta có thể thấy rằng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
037 thực sự là một thể hiện của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79 – class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 nằm trong chuỗi nguyên mẫu của nó29. 7. 4. 2 Chuỗi nguyên mẫu của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
043Chuỗi nguyên mẫu của một Mảng trông như thế nào?
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
74Hình 17. Chuỗi nguyên mẫu của một Mảng có các thành viên này. thể hiện Mảng, class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
044, class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87, class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
031Chuỗi nguyên mẫu này [được hiển thị trong hình. 17] cho chúng ta biết rằng một đối tượng Array là một thể hiện của
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
047 và của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
7929. 7. 4. 3 Chuỗi nguyên mẫu của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
049Cuối cùng, chuỗi nguyên mẫu của một hàm thông thường cho chúng ta biết rằng tất cả các hàm đều là đối tượng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
7529. 7. 4. 4 Chuỗi nguyên mẫu của các lớp dựng sẵnNguyên mẫu của một lớp cơ sở là
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
008 có nghĩa là nó là một hàm [một thể hiện của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
051]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
76Nguyên mẫu của lớp dẫn xuất là lớp cha của nó
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
77Thật thú vị,
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79, class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
047 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
051 đều là các lớp cơ sởclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
78Tuy nhiên, như chúng ta đã thấy, ngay cả các thể hiện của các lớp cơ sở cũng có
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 trong chuỗi nguyên mẫu của chúng vì nó cung cấp các dịch vụ mà tất cả các đối tượng cầnTại sao lại là các lớp cơ sở
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
047 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
051?Base classes are where instances are actually created. Cả
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
047 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
051 đều cần tạo các phiên bản của riêng chúng vì chúng có cái gọi là "khe nội bộ" mà sau này không thể thêm vào các phiên bản được tạo bởi class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
7929. 7. Lớp 5 Mixin [nâng cao]
Hệ thống lớp của JavaScript chỉ hỗ trợ kế thừa đơn. Tức là mỗi lớp có thể có nhiều nhất một lớp cha. Một cách để giải quyết hạn chế này là thông qua một kỹ thuật gọi là các lớp mixin [viết tắt. hỗn hợp]
Ý tưởng là như sau. Giả sử chúng ta muốn một lớp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
57 kế thừa từ hai lớp cha class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
062 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
063. Đó sẽ là đa kế thừa mà JavaScript không hỗ trợCách giải quyết của chúng tôi là biến
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
062 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
063 thành mixin, nhà máy cho các lớp conclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79Mỗi hàm trong số hai hàm này trả về một lớp mở rộng một siêu lớp đã cho
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
066. Ta tạo lớp class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
57 như sauclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
00Bây giờ chúng ta có một lớp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
57 mở rộng lớp được trả về bởi class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
069 mở rộng lớp được trả về bởi class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
070 mở rộng cho class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
7929. 7. 5. 1 Ví dụ. một mixin để quản lý thương hiệuChúng tôi triển khai một mixin
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
072 có các phương thức trợ giúp để thiết lập và nhận thương hiệu của một đối tượngclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
01Chúng tôi sử dụng mixin này để triển khai lớp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
073 có tênclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
02Đoạn mã sau xác nhận rằng mixin hoạt động
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0329. 7. 5. 2 Lợi ích của mixinMixins giải phóng chúng ta khỏi những ràng buộc của thừa kế đơn lẻ
- Cùng một lớp có thể mở rộng một siêu lớp và không hoặc nhiều mixin
- Nhiều lớp có thể sử dụng cùng một mixin
29. 8 Các phương thức và bộ truy cập của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 [nâng cao]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Như chúng ta đã thấy ở §29. 7. 3 “Không phải tất cả các đối tượng đều là phiên bản của
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79”, hầu hết tất cả các đối tượng đều là phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79. Lớp này cung cấp một số phương thức hữu ích và một trình truy cập vào các thể hiện của nó- Định cấu hình cách các đối tượng được chuyển đổi thành các giá trị nguyên thủy [e. g. bởi nhà điều hành
077]. Các phương thức sau đây có cài đặt mặc định nhưng thường bị ghi đè trong các lớp con hoặc phiên bảnclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
078. Cấu hình cách một đối tượng được chuyển đổi thành một chuỗiclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
079. Phiên bản củaclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
078 có thể được định cấu hình theo nhiều cách khác nhau thông qua các đối số [ngôn ngữ, khu vực, v.v. ]class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
081. Định cấu hình cách đối tượng được chuyển đổi thành giá trị nguyên thủy không phải chuỗi [thường là số]class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Các phương pháp hữu ích [có cạm bẫy - xem tiểu mục tiếp theo]
- Tránh các tính năng này [có những lựa chọn thay thế tốt hơn]
74. Nhận và thiết lập nguyên mẫu của máy thuclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Không nên sử dụng bộ truy cập này. lựa chọn thay thế
083class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
084class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Không nên sử dụng bộ truy cập này. lựa chọn thay thế
085. Người nhận có thuộc tính riêng với khóa đã cho không?class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Sử dụng phương pháp này không được khuyến khích. Thay thế trong ES2022 trở lên.
086class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Sử dụng phương pháp này không được khuyến khích. Thay thế trong ES2022 trở lên.
Trước khi xem xét kỹ hơn từng tính năng này, chúng ta sẽ tìm hiểu về một cạm bẫy quan trọng [và cách khắc phục nó]. Chúng tôi không thể sử dụng các tính năng của
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 với tất cả các đối tượng29. 8. 1 Sử dụng phương pháp class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 một cách an toàn
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Gọi một trong các phương thức của
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 trên một đối tượng tùy ý không phải lúc nào cũng hoạt động. Để minh họa lý do tại sao, chúng tôi sử dụng phương thức class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
090, trả về class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
091 nếu một đối tượng có thuộc tính riêng với khóa đã choclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
04Gọi
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
085 trên một đối tượng tùy ý có thể thất bại theo hai cách. Một mặt, phương thức này không khả dụng nếu một đối tượng không phải là một thể hiện của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79 [xem §29. 7. 3 “Không phải tất cả các đối tượng đều là phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79”]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
05Mặt khác, chúng ta không thể sử dụng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
085 nếu một đối tượng ghi đè lên nó bằng một thuộc tính riêng [dòng A]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
06Tuy nhiên, có một cách an toàn để sử dụng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
085class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
07Lời gọi phương thức trong dòng A được giải thích trong §29. 3. 5 “Công văn vs. gọi phương thức trực tiếp”
Chúng tôi cũng có thể sử dụng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
097 để thực hiện class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
098class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
08Cái này hoạt động ra sao? . Tuy nhiên, nếu chúng ta muốn gọi hàm, chúng ta không thể trích xuất nó một cách đơn giản, chúng ta cũng phải đảm bảo rằng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
22 của nó luôn có giá trị phù hợp. Đó là những gì class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
097 làmCó bao giờ sử dụng các phương thức
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 thông qua công văn động không?Trong một số trường hợp, chúng ta có thể lười biếng và gọi các phương thức
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 như các phương thức bình thường [không có class Person {
#firstName; // [A]
constructor[firstName] {
this.#firstName = firstName; // [B]
}
describe[] {
return `Person named ${this.#firstName}`;
}
static extractNames[persons] {
return persons.map[person => person.#firstName];
}
}
04 hoặc class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
097]. Nếu chúng ta biết người nhận và chúng là những đối tượng có bố cục cố địnhMặt khác, nếu chúng tôi không biết người nhận của họ và/hoặc họ là đối tượng từ điển, thì chúng tôi cần đề phòng
29. 8. 2 ____1607
Bằng cách ghi đè
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
078 [trong một lớp con hoặc một thể hiện], chúng ta có thể định cấu hình cách các đối tượng được chuyển đổi thành chuỗiclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
09Để chuyển đổi các đối tượng thành chuỗi, tốt hơn là sử dụng
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
609 vì nó cũng hoạt động với class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
610 và class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
031class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0029. 8. 3 ____1612
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
079 là phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
078 có thể được định cấu hình thông qua ngôn ngữ và thường là các tùy chọn bổ sung. Bất kỳ lớp hoặc cá thể nào cũng có thể triển khai phương thức này. Trong thư viện tiêu chuẩn, các lớp sau đây làm
615class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
616class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
617class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
618class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
619class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
Ví dụ: đây là cách các số có phân số thập phân được chuyển đổi thành chuỗi khác nhau, tùy thuộc vào ngôn ngữ [
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
620 là tiếng Pháp, class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
621 là tiếng Anh]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0129. 8. 4 ____1622
Bằng cách ghi đè
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
081 [trong một lớp con hoặc một thể hiện], chúng ta có thể định cấu hình cách các đối tượng được chuyển đổi thành giá trị không phải chuỗi [thường là số]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0229. 8. 5 ____1624
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
625 trả về class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
091 nếu class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
627 nằm trong chuỗi nguyên mẫu của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
29 và ngược lại là class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
021class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
03Đây là cách sử dụng phương pháp này một cách an toàn [chi tiết xem §29. 8. 1 “Sử dụng phương pháp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 một cách an toàn”]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0429. 8. 6 ____1631
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
632 trả về class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
091 nếu class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
29 có thuộc tính đếm được riêng có khóa là class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
635 và ngược lại là class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
021class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
05Đây là cách sử dụng phương pháp này một cách an toàn [chi tiết xem §29. 8. 1 “Sử dụng phương pháp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 một cách an toàn”]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
06Một giải pháp thay thế an toàn khác là sử dụng các bộ mô tả thuộc tính
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0729. 8. 7 class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
638 [người truy cập]
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Thuộc tính
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
639 tồn tại trong hai phiên bản- Một trình truy cập mà tất cả các phiên bản của
79 đều cóclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Một thuộc tính của các đối tượng bằng chữ đặt các nguyên mẫu của các đối tượng do chúng tạo ra
Tôi khuyên bạn nên tránh tính năng cũ
Ngược lại,
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
639 theo nghĩa đen của đối tượng luôn hoạt động và không bị phản đốiĐọc tiếp nếu bạn quan tâm đến cách thức hoạt động của trình truy cập
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
639class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
639 là một bộ truy cập của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 được kế thừa bởi tất cả các phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79. Thực hiện nó thông qua một lớp sẽ như thế nàyclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
08Vì
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
639 được kế thừa từ class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87, chúng tôi có thể loại bỏ tính năng này bằng cách tạo một đối tượng không có class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 trong chuỗi nguyên mẫu của nó [xem §29. 7. 3 “Không phải tất cả các đối tượng đều là phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
79”]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
0929. 8. 8 ____1650
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
651 trả về class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
091 nếu class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
29 có thuộc tính riêng [không được thừa kế] có khóa là class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
635 và ngược lại là class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
021class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
10Đây là cách sử dụng phương pháp này một cách an toàn [chi tiết xem §29. 8. 1 “Sử dụng phương pháp
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
87 một cách an toàn”]class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
1129. 9 Câu hỏi thường gặp. các lớp học
29. 9. 1 Tại sao chúng được gọi là “trường cá thể riêng” trong cuốn sách này mà không phải là “trường cá thể riêng”?
Điều đó được thực hiện để làm nổi bật các thuộc tính khác nhau [các vị trí công khai] và các vị trí riêng tư như thế nào. Bằng cách thay đổi thứ tự của các tính từ, các từ “public” và “field” và các từ “riêng tư” và “field” luôn được đề cập cùng nhau
29. 9. 2 Tại sao lại là tiền tố định danh class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
24?
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
Các trường riêng tư có thể được khai báo qua
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
658 và sử dụng số nhận dạng thông thường không? class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
12Bất cứ khi nào một biểu thức chẳng hạn như
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
660 xuất hiện trong phần thân của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
36, JavaScript phải quyết định
662 có phải là tài sản không?class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
662 có phải là trường riêng không?class Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
Tại thời điểm biên dịch, JavaScript không biết liệu khai báo trong dòng A có áp dụng cho
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
664 [do nó là phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
36] hay không. Điều đó để lại hai lựa chọn để đưa ra quyết định
662 luôn được hiểu là trường riêngclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- JavaScript quyết định trong thời gian chạy
- Nếu
664 là một thể hiện củaclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
36, thìclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
662 được hiểu là trường riêngclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Mặt khác,
662 được hiểu là thuộc tínhclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Nếu
Cả hai lựa chọn đều có nhược điểm
- Với tùy chọn [1], chúng tôi không thể sử dụng
662 làm thuộc tính nữa – cho bất kỳ đối tượng nàoclass Employee extends Person { constructor[firstName, title] { super[firstName]; this.title = title; // [C] } describe[] { return super.describe[] + ` [${this.title}]`; } } const jane = new Employee['Jane', 'CTO']; assert.equal[ jane.title, 'CTO' ]; assert.equal[ jane.describe[], 'Person named Jane [CTO]' ];
- Với tùy chọn [2], hiệu suất bị ảnh hưởng tiêu cực
Đó là lý do tại sao tiền tố tên
class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
24 được giới thiệu. Quyết định bây giờ thật dễ dàng. Nếu chúng tôi sử dụng class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
24, chúng tôi muốn truy cập vào một trường riêng tư. Nếu không, chúng tôi muốn truy cập vào một thuộc tínhclass Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
658 hoạt động cho các ngôn ngữ được nhập tĩnh [chẳng hạn như TypeScript] vì chúng biết tại thời điểm biên dịch nếu class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
664 là một phiên bản của class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
36 và sau đó có thể coi class Employee extends Person {
constructor[firstName, title] {
super[firstName];
this.title = title; // [C]
}
describe[] {
return super.describe[] +
` [${this.title}]`;
}
}
const jane = new Employee['Jane', 'CTO'];
assert.equal[
jane.title,
'CTO'
];
assert.equal[
jane.describe[],
'Person named Jane [CTO]'
];
662 là riêng tư hoặc công khai