Trong lập trình hướng đối tượng, một lớp là một mẫu mã chương trình có thể mở rộng để tạo các đối tượng, cung cấp các giá trị ban đầu cho trạng thái (các biến thành viên) và triển khai hành vi (các hàm hoặc phương thức thành viên) WikipediaTrong thực tế, chúng ta thường cần tạo nhiều đối tượng cùng loại, chẳng hạn như người dùng, hàng hóa hoặc bất cứ thứ gì Như chúng ta đã biết từ chương Constructor, toán tử "new", class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 8 có thể giúp ích cho việc đóNhưng trong JavaScript hiện đại, có một cấu trúc “lớp” nâng cao hơn, giới thiệu các tính năng mới tuyệt vời hữu ích cho lập trình hướng đối tượng Cú pháp cơ bản là class MyClass {
// class methods
constructor() { .. }
method1() { .. }
method2() { .. }
method3() { .. }
...
}
Sau đó sử dụng class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 9 để tạo một đối tượng mới với tất cả các phương thức được liệt kêPhương thức class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 0 được gọi tự động bởi class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 1, vì vậy chúng ta có thể khởi tạo đối tượng ở đóVí dụ class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi();
Khi class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 2 được gọi- Một đối tượng mới được tạo
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 3 chạy với đối số đã cho và gán nó cho class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 4
…Sau đó, chúng ta có thể gọi các phương thức đối tượng, chẳng hạn như class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 5Không có dấu phẩy giữa các phương thức lớp Một cạm bẫy phổ biến đối với các nhà phát triển mới làm quen là đặt dấu phẩy giữa các phương thức của lớp, điều này sẽ dẫn đến lỗi cú pháp Ký hiệu ở đây không được nhầm lẫn với nghĩa đen của đối tượng. Trong lớp, không cần dấu phẩy Vì vậy, chính xác thì một class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 6 là gì? Hãy tiết lộ bất kỳ phép thuật nào và xem lớp học thực sự là gì. Điều đó sẽ giúp hiểu được nhiều khía cạnh phức tạp Trong JavaScript, một lớp là một loại chức năng Đây, hãy xem class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function
Điều mà cấu trúc class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 7 thực sự làm là- Tạo một hàm có tên là
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 8, trở thành kết quả của khai báo lớp. Mã chức năng được lấy từ phương thức class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 3 (giả sử trống nếu chúng ta không viết phương thức đó) - Lưu trữ các phương thức của lớp, chẳng hạn như
class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi 0, trong class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi 1
Sau khi đối tượng class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi 2 được tạo, khi chúng ta gọi phương thức của nó, nó được lấy từ nguyên mẫu, giống như được mô tả trong chương F. nguyên mẫu. Vì vậy, đối tượng có quyền truy cập vào các phương thức lớpChúng ta có thể minh họa kết quả của khai báo class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi 3 nhưĐây là mã để hướng nội nó class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi
Đôi khi người ta nói rằng class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 6 là một "đường cú pháp" (cú pháp được thiết kế để làm cho mọi thứ dễ đọc hơn, nhưng không giới thiệu bất cứ điều gì mới), bởi vì chúng ta thực sự có thể khai báo cùng một điều mà không cần sử dụng từ khóa class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 6// rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi();
Kết quả của định nghĩa này gần giống. Vì vậy, thực sự có những lý do tại sao class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 6 có thể được coi là một đường cú pháp để định nghĩa một hàm tạo cùng với các phương thức nguyên mẫu của nóTuy nhiên, vẫn có những khác biệt quan trọng Đầu tiên, một hàm được tạo bởi class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 6 được gắn nhãn bởi một thuộc tính bên trong đặc biệt class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi 8. Vì vậy, nó không hoàn toàn giống như tạo thủ côngNgôn ngữ kiểm tra thuộc tính đó ở nhiều nơi. Ví dụ, không giống như một chức năng thông thường, nó phải được gọi bằng class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 1class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new'
Ngoài ra, một biểu diễn chuỗi của hàm tạo lớp trong hầu hết các công cụ JavaScript bắt đầu bằng “lớp…” class User {
constructor() {}
}
alert(User); // class User { .. }
Có những khác biệt khác, chúng ta sẽ sớm thấy chúng Các phương thức lớp không thể đếm được. Một định nghĩa lớp đặt cờ // rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi(); 0 thành // rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi(); 1 cho tất cả các phương thức trong // rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi(); 2Điều đó tốt, bởi vì nếu chúng ta // rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi(); 3 trên một đối tượng, chúng ta thường không muốn các phương thức lớp của nóCác lớp học luôn // rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi(); 4. Tất cả mã bên trong cấu trúc lớp sẽ tự động ở chế độ nghiêm ngặt
Ngoài ra, cú pháp class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 6 còn mang đến nhiều tính năng khác mà chúng ta sẽ khám phá sauCũng giống như các hàm, các lớp có thể được định nghĩa bên trong một biểu thức khác, được chuyển qua, trả về, được gán, v.v. Đây là một ví dụ về một biểu thức lớp let User = class {
sayHi() {
alert("Hello");
}
};
Tương tự như Biểu thức hàm được đặt tên, biểu thức lớp có thể có tên Nếu một biểu thức lớp có tên, nó chỉ hiển thị bên trong lớp // "Named Class Expression"
// (no such term in the spec, but that's similar to Named Function Expression)
let User = class MyClass {
sayHi() {
alert(MyClass); // MyClass name is visible only inside the class
}
};
new User().sayHi(); // works, shows MyClass definition
alert(MyClass); // error, MyClass name isn't visible outside of the class
Chúng tôi thậm chí có thể tạo các lớp động "theo yêu cầu", như thế này function makeClass(phrase) {
// declare a class and return it
return class {
sayHi() {
alert(phrase);
}
};
}
// Create a new class
let User = makeClass("Hello");
new User().sayHi(); // Hello
Giống như các đối tượng theo nghĩa đen, các lớp có thể bao gồm getters/setters, các thuộc tính được tính toán, v.v. Đây là một ví dụ cho // rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi(); 6 được triển khai bằng cách sử dụng // rewriting class User in pure functions
// 1. Create constructor function
function User(name) {
this.name = name;
}
// a function prototype has "constructor" property by default,
// so we don't need to create it
// 2. Add the method to prototype
User.prototype.sayHi = function() {
alert(this.name);
};
// Usage:
let user = new User("John");
user.sayHi(); 7class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 0Về mặt kỹ thuật, khai báo lớp như vậy hoạt động bằng cách tạo getters và setters trong class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi 1Đây là một ví dụ với tên phương thức được tính toán sử dụng dấu ngoặc _______ 22_______9 class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 1Các tính năng như vậy rất dễ nhớ, vì chúng giống với các đối tượng theo nghĩa đen Các trình duyệt cũ có thể cần một polyfill Các trường lớp là một bổ sung gần đây cho ngôn ngữ Trước đây, các lớp của chúng ta chỉ có các phương thức “Trường lớp” là một cú pháp cho phép thêm bất kỳ thuộc tính nào Chẳng hạn, hãy thêm thuộc tính class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 0 vào class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi 3class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 2Vì vậy, chúng ta chỉ cần viết "=" trong phần khai báo, thế là xong Sự khác biệt quan trọng của các trường lớp là chúng được đặt trên các đối tượng riêng lẻ, không phải class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// class is a function
alert(typeof User); // function
// ...or, more precisely, the constructor method
alert(User === User.prototype.constructor); // true
// The methods are in User.prototype, e.g:
alert(User.prototype.sayHi); // the code of the sayHi method
// there are exactly two methods in the prototype
alert(Object.getOwnPropertyNames(User.prototype)); // constructor, sayHi 1class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 3Chúng ta cũng có thể gán giá trị bằng cách sử dụng các biểu thức và lệnh gọi hàm phức tạp hơn class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 4Như đã trình bày trong chương Các hàm liên kết hàm trong JavaScript có một class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 3 động. Nó phụ thuộc vào bối cảnh của cuộc gọiVì vậy, nếu một phương thức đối tượng được truyền xung quanh và được gọi trong ngữ cảnh khác, thì class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 3 sẽ không còn là tham chiếu đến đối tượng của nó nữaChẳng hạn, mã này sẽ hiển thị class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 5class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 5Vấn đề được gọi là "mất class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 3"Có hai cách để khắc phục nó, như đã thảo luận trong chương Ràng buộc chức năng - Truyền hàm bao bọc, chẳng hạn như
class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 7 - Liên kết phương thức với đối tượng, e. g. trong hàm tạo
Các trường lớp cung cấp một cú pháp khác, khá tao nhã class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 6Trường lớp class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 8 được tạo trên cơ sở từng đối tượng, có một hàm riêng cho từng đối tượng class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 9, với _______27_______3 bên trong nó tham chiếu đến đối tượng đó. Chúng tôi có thể vượt qua class User {
constructor() {}
}
alert(User); // class User { .. } 1 ở bất cứ đâu và giá trị của class User {
constructor() {}
}
alert(typeof User); // function
User(); // Error: Class constructor User cannot be invoked without 'new' 3 sẽ luôn đúngĐiều đó đặc biệt hữu ích trong môi trường trình duyệt, dành cho người nghe sự kiện Cú pháp lớp cơ bản trông như thế này class User {
constructor(name) {
this.name = name;
}
sayHi() {
alert(this.name);
}
}
// Usage:
let user = new User("John");
user.sayHi(); 7class User {
constructor() {}
}
alert(User); // class User { .. } 3 về mặt kỹ thuật là một hàm (hàm mà chúng tôi cung cấp là class User {
constructor(name) { this.name = name; }
sayHi() { alert(this.name); }
}
// proof: User is a function
alert(typeof User); // function 3), trong khi các phương thức, getters và setters được viết cho class User {
constructor() {}
}
alert(User); // class User { .. } 5
Chúng ta có thể viết phương thức bên ngoài lớp không?
Định nghĩa của các phương thức lớp có thể ở bất kỳ đâu bên ngoài lớp . Khi bạn định nghĩa một phương thức lớp bên ngoài lớp, bạn cần thêm tiền tố vào tên phương thức với tên lớp và toán tử phân giải phạm vi. Phần quan trọng là không sử dụng các từ khóa truy cập phạm vi, chẳng hạn như riêng tư, được bảo vệ hoặc công khai.
Làm cách nào để thêm một phương thức vào một lớp trong JavaScript?
Các phương thức của lớp được tạo với cú pháp giống như các phương thức của đối tượng. Sử dụng từ khóa lớp để tạo lớp. Luôn thêm phương thức constructor(). Sau đó, thêm bất kỳ số lượng phương thức nào .
Chúng ta có thể khai báo phương thức bên ngoài lớp trong Java không?
Bạn có thể có các phương thức công khai trong các lớp không công khai , nhưng bạn có thể không muốn điều đó vì các lớp không công khai sẽ bị hạn chế (có lẽ không có) khả năng hiển thị bên ngoài .
Chúng ta có thể định nghĩa một phương thức bên ngoài lớp như thế nào và tại sao không?
Có, bạn chắc chắn có thể có các hàm bên ngoài lớp học . |