Lớp

ES6 giới thiệu khái niệm "lớp" trong JavaScript. Khái niệm này khác với lớp trong các ngôn ngữ lập trình khác. Ở đây, lớp là các hàm đặc biệt đóng vai trò là mẫu để tạo đối tượng đã chứa dữ liệu, thuộc tính liên kết với dữ liệu đó và các phương thức liên quan đến việc thao túng dữ liệu đó. Các đối tượng, thuộc tính và phương thức này được gọi chung là "thành phần" của lớp.

Để xác định một lớp, hãy sử dụng từ khoá class. Hãy làm theo phương pháp hay nhất và quy ước do các hàm khởi tạo tích hợp của JavaScript thiết lập, bắt đầu bất kỳ giá trị nhận dạng nào của lớp bằng một chữ cái viết hoa:

class MyClass {}

Lớp nhằm cung cấp nhiều cách dễ tiếp cận hơn để làm việc với các tính năng nâng cao của nguyên mẫu và hàm khởi tạo:

class MyClass {}

typeof MyClass;
> "function"

Vì các lớp đã được thêm một phần để giúp việc làm việc với các tính năng JavaScript nâng cao dễ dàng và hấp dẫn hơn, nên đôi khi chúng được gọi là "cú pháp dễ hiểu". Tuy nhiên, lớp không chỉ cung cấp cách viết tắt hữu ích khi làm việc với tính kế thừa nguyên mẫu. Ra mắt các cơ hội tạo cú pháp lớp để giải quyết các vấn đề thiết kế lâu dài trong JavaScript mà không gây ra các vấn đề về khả năng tương thích ngược. Ví dụ: tất cả các mã bên trong phần nội dung của một lớp luôn được đánh giá ở chế độ nghiêm ngặt.

Để tạo một thực thể của một lớp, hãy dùng toán tử new.

class MyClass {}

const myClassInstance = new MyClass();

myClassInstance;
> Object { }

Các hàm được xác định bên trong phần nội dung của lớp sẽ hiển thị dưới dạng phương thức của từng thực thể của lớp đó.

class MyClass {
    classMethod() {
        console.log( "My class method." );
    }
}

const myClassInstance = new MyClass();

myClassInstance.classMethod();
> "My class method."

Phương thức được xác định trong một lớp sẽ trở thành phương thức trên nguyên mẫu của thực thể thu được. Do tính chất của chuỗi nguyên mẫu, bạn có thể gọi các phương thức này ngay trên đối tượng thu được:

class MyClass {
  classMethod() {
    console.log( "My class method." );
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance;
> Object { }
    <prototype>: Object { … }
        classMethod: function classMethod()
        constructor: class MyClass { constructor(myPassedValue) }
        <prototype>: Object { … }

myClassInstance.classMethod();
> "My class method."

Việc tạo một thực thể của lớp sẽ gọi một phương thức constructor() đặc biệt. Phương thức này sẽ thực hiện mọi hoạt động "thiết lập" cần thiết cho thực thể mới tạo và khởi chạy mọi thuộc tính liên kết với thực thể đó. Bất kỳ đối số nào được chuyển đến lớp khi thực thể được tạo đều có thể sử dụng cho phương thức constructor():

class MyClass {
  constructor( myPassedValue ) {
    console.log( myPassedValue );
  }
}

const myClassInstance = new MyClass( "A string." );
> "A string."

Trong phần nội dung của một lớp, giá trị của this tham chiếu đến chính thực thể đó, với mọi thuộc tính được xác định trên this hiển thị dưới dạng thuộc tính của từng thực thể của lớp đó:

class MyClass {
  constructor( myPassedValue ) {
    this.instanceProperty = myPassedValue;
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance;
> Object { instanceProperty: "A string." }

Bạn cũng có thể sử dụng các thuộc tính này cho tất cả các phương thức trong phần nội dung của lớp:

class MyClass {
  constructor( myPassedValue ) {
    this.instanceProp = myPassedValue;
  }
  myMethod() {
    console.log( this.instanceProp );
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance.myMethod();
> "A string."

Nếu bạn không xác định constructor() cho lớp của mình, công cụ JavaScript sẽ giả định một constructor "mặc định" trống. Mỗi lớp chỉ có thể có một phương thức đặc biệt tên là constructor():

class MyClass {
  constructor() {}
  constructor() {}
}
> Uncaught SyntaxError: A class may only have one constructor

Bạn có thể xác định một lớp bằng cách sử dụng phần khai báo lớp hoặc biểu thức lớp. Các ví dụ trước đây đều là khai báo lớp, yêu cầu gọi tên bằng new. Bạn có thể đặt tên hoặc để trống tên của biểu thức lớp để tạo lớp "ẩn danh".

let ClassExpression = class {
    constructor() {}
};

ClassExpression;
> class  {}

Bạn có thể sử dụng biểu thức lớp ẩn danh cho các hàm tạo lớp "nhanh chóng":

function classMaker() {
  return class {
    constructor() {}
  };
}

let MyVariable = classMaker();

MyVariable;
> class  {}

Việc khai báo lại một lớp bằng phần khai báo lớp sẽ gây ra lỗi cú pháp:


class MyClass {
    constructor( ) {
        console.log( "My class." );
    }
};

class MyClass {
    constructor() {
        console.log( "My new class." );
    }
};
> Uncaught SyntaxError: redeclaration of class MyClass

Tuy nhiên, biểu thức lớp cho phép bạn xác định lại một lớp:

let ClassExpression = class MyClass { };

ClassExpression = class MyOtherClass {
    constructor( myString ) {
        this.myProp = myString;
    }
};

new ClassExpression( "String." );
> MyOtherClass {myProp: 'String.'}

Bạn không thể gọi một biểu thức lớp được đặt tên theo tên như cách bạn có thể khai báo lớp. Tuy nhiên, tên được chỉ định của biểu thức lớp có sẵn dưới dạng thuộc tính của thực thể đã tạo, chủ yếu là để gỡ lỗi dễ dàng hơn:

let MyVariable = class MyClass {};

MyClass;
> Uncaught ReferenceError: MyClass is not defined

MyVariable;
> class MyClass {}

MyVariable.name;
> "MyClass"

Khi bạn khởi tạo một biến bằng biểu thức lớp, các quy tắc chuyển lên trên của biến đó sẽ được tuân theo như dự kiến. Nội dung khai báo lớp tuân theo cùng các quy tắc "vùng điểm chết tạm thời" như letconst, và hoạt động như thể chúng chưa được chuyển lên đầu phạm vi hiện tại, tức là việc gọi một lớp trước khi khai báo lớp sẽ gây ra lỗi:

{
    let myVar = new MyClass( "Property string." );

    class MyClass {
        myProp;

        constructor( myString ) {
            this.myProp = myString;
        }
    };
};
> Uncaught ReferenceError: Cannot access 'MyClass' before initialization

Kiểm tra kiến thức

Câu nào sau đây xác định đúng về lớp?

class MyClass {}
myClass = class {}
new class()

Một lớp có thể có bao nhiêu phương thức constructor()?

Một
Không có
Vé loại không giới hạn