Class trong JavaScript

Ngày đăng: 12/10/2020   -    Cập nhật: 13/10/2020


Hôm nay mình sẽ giới thiệu với bạn về class trong JavaScript. Class được tạo ra như thế nào? Sử dụng class ra sao. Hãy theo dõi nhé!

Class trong JavaScript

1. Class là gì?


Class có thể hiểu là một khuôn mẫu.

Trong lập trình hướng đối tượng class (hay lớp) được sử dụng để tạo ra các đối tượng (mà mình đã giới thiệu ở bài đối tượng trong JavaScript).

Đối tượng thì sẽ có các thuộc tính, phương thức.

Các đối tượng giống nhau sẽ có những thuộc tính và phương thức giống nhau.

Từ phiên bản ECMAScript 6 thì JavaSript hỗ trợ tạo ra class giống các ngôn ngữ lập trình hướng đối tượng khác (Java, PHP, Python...).



Tham khảo:


Có thể xem như việc sử dụng class và object sẽ giúp chúng ta có cái nhìn chuẩn hơn về code và để những bạn mới tiếp cận lập trình JavaSript cũng thấy gần gũi hơn.

Cú pháp để tạo ra một class trong JavaSript:



class TenClass {
    // Hàm khởi tạo
    constructor() { ... }
    // Các phương thức
    phuongThuc1() { ... }
    phuongThuc2() { ... }
    phuongThuc3() { ... }
    }
}
 

Đây là ví dụ khi khai báo Object mà mình đã giới thiệu ở bài trước:


let SinhVien = {

    // Tạo các thuộc tính
    hoTen: 'Ngô Minh Trung',
    gioiTinh: 'Nam',
    MSSV: 'B1704863',
    namSinh: '1999',

    // Tạo các phương thức
    hocBai: function() {
        console.log('Đang học bài...');
    },
    diNgu: function() {
        console.log('Đang ngủ...');
    },
    xemPhim: function() {
        console.log('Đang xem phim...');
    }
}
 

Nhưng ở đây, ta chỉ tạo được một đối tượng cụ thể.

Nếu muốn tạo ra đối tượng khác thì ta lại phải viết code lại gần như từ đầu.

Nếu các đối tượng sinh viên tạo ra cũng có các thuộc tính giống nhau như: hoTen, gioiTinh, MSSV, namSinh...

Và các thuộc tính chung như hocBai, diNgu, xemPhim....

Thì có nghĩa là code của bạn chưa tối ưu.

Code thừa rất nhiều.

Để tránh vấn đề này, chúng ta có class:



// Tạo ra một class SinhVien
class SinhVien {
    //Hàm khởi tạo 
    constructor(hoTengioiTinhMSSVnamSinh) {
        this.hoTen = hoTen;
        this.gioiTinh = gioiTinh;
        this.namSinh = namSinh;
        this.MSSV = MSSV;
    }
    
    //Khai báo phương thức
    hocBai() {
        console.log('Đang học bài...');
    }
    diNgu() {
        console.log('Đang ngủ...');
    }
    xemPhim() {
        console.log('Đang xem phim...');
    }

}
 

Đây có thể hiểu như là một khuôn mẫu chung cho các đối tượng sinh viên.

Khi muốn tạo ra đối tượng cụ thể thì ta sẽ sử dụng class SinhVien này.



// Tạo đối tượng từ class SinhVien
var sinhVien1 = new SinhVien();
var sinhVien2 = new SinhVien();
var sinhVien3 = new SinhVien();
 

> Lưu ý: Theo quy tắc thì bạn nên đặt tên class là viết HOA chữ cái đầu tiên như SinhVien, GiangVien, NhanVien...

2. Constructor là gì?


Phương thức khởi tạo (constructor hay là hàm khởi tạo) là một phương thức đặc biệt để tạokhởi tạo một đối tượng từ một class nào đó.

Nó sẽ tự động được gọi khi bạn tạo ra một đối tượng từ class.

Chỉ có thể có một phương thức đặc biệt với tên là “constructor” trong một lớp.

Một lỗi syntaxError sẽ được quăng ra nếu lớp có nhiều hơn một lần xuất hiện của một phương thức khởi tạo.

Tức là JavaScript không hỗ trợ có nhiều constructor như các ngôn ngữ khác.

Một ví dụ về constructor:



//Hàm khởi tạo 
constructor(hoTengioiTinhMSSVnamSinh) {
    this.hoTen = hoTen;
    this.gioiTinh = gioiTinh;
    this.namSinh = namSinh;
    this.MSSV = MSSV;
}
 

Như vậy để tạo hàm constructor thì chỉ cần dùng từ khóa constructor và truyền vào danh sách tham số là các thuộc tính của class.

Sau đó gán các thuộc tính của lớp bằng từ khóa this.

Bạn nhìn như thế này sẽ dễ hiểu hơn:



constructor(abcd) {
    this.hoTen = a;
    this.gioiTinh = b;
    this.namSinh = c;
    this.MSSV = d;
}
 

Sau đó khi khởi tạo đối tượng thì ta sẽ truyền đối số như thế này:


var sinhVien1 = new SinhVien(abcd);
 

Tuy nhiên, để sau này dễ dàng biết thuộc tính nào kết nối với tham số nào thì chúng ta nên sử dụng tên tham số và đối số trong hàm constructor giống nhau.


//Hàm khởi tạo 
constructor(hoTengioiTinhMSSVnamSinh) {
    this.hoTen = hoTen;
    this.gioiTinh = gioiTinh;
    this.namSinh = namSinh;
    this.MSSV = MSSV;
}
 

> Ghi chú: Khi tạo class thì ta gọi là tham số. Khi khởi tạo và truyền dữ liệu thì ta gọi nó là đối số

Chúng ta có nhiều cách gọi hàm như trong bài hàm mình có đề cập đến.

Ví dụ như sau:



// Khởi tạo các đối tượng sinh viên
var sinhVien1 = new SinhVien("Ngô Minh Trung""Nam""B1704863""1999");
var sinhVien2 = new SinhVien("Nguyễn Minh Đức""Nam");
var sinhVien3 = new SinhVien();

// Log ra thông tin đối tượng
console.log(sinhVien1);
console.log(sinhVien2);
console.log(sinhVien3);
 

Kết quả ta được như sau:

Ví dụ tạo đối tượng từ class

> Lưu ý: Kể cả khi bạn không định nghĩa rõ ràng một constructor. JavaScript cũng sẽ tự động thêm vào một constructor rỗng

3. Phương thức getter và setter trong JavaScript


Các phương thức getter và setter được sử dụng để truy cập / sửa đổi thuộc tính trong class.

Có thể hiểu là một loại hàm để lấy dữ liệu và một loại hàm dùng đế gán dữ liệu.

3.1. Phương thức getter


Các phương thức getter được sử dụng để truy cập các thuộc tính của một đối tượng.

Để tạo phương thức getter trong JavaScript, chúng ta sử dụng từ khóa get.

Ví dụ:


// Các phương thức getter
get getHoTen() {
    return this.hoTen;
}
get getGioiTinh() {
    return this.gioiTinh;
}
get getNamSinh() {
    return this.hoTen;
}
get getMSSV() {
    return this.MSSV;
}
 

Có bao nhiêu thuộc tính thì sẽ có bấy nhiêu hàm getter trong class.

Khi chúng ta sử dụng, chúng ta có thể truy cập giá trị như là một thuộc tính.

Ví dụ:



// Khởi tạo đối tượng
var sinhVien1 = new SinhVien("Ngô Minh Trung""Nam""B1704863""1999");

// Truy cập giới tính thông qua phương thức getter
console.log(sinhVien1.getGioiTinh);
 

Ngay cả khi getter là một phương thức, nếu bạn cố gắng truy cập giá trị dưới dạng một phương thức (sử dụng ngoặc tròn () ) như thế này:


console.log(sinhVien1.getGioiTinh());
 

Thì sẽ bị lỗi:

Uncaught TypeError: sinhVien1.getGioiTinh is not a function


3.2. Phương thức setter


Phương thức setter cho phép bạn thay đổi giá trị của thuộc tính của đối tượng.

Để tạo ra phương thức setter ta sử dụng từ khóa set

Ví dụ:



set setHoTen(hoTen) {
    this.hoTen = hoTen;
}

set setGioiTinh(gioiTinh) {
    this.gioiTinh = gioiTinh;
}
set setNamSinh(namSinh) {
    this.namSinh = namSinh;
}
set setMSSV(MSSV) {
    this.MSSV = MSSV;
}
 

Cũng tương tự getter, setter cũng vậy có bao nhiêu thuộc tính thì chúng ta tạo bấy nhiêu hàm setter.

Để sử dụng phương thức setter bạn phải truyền vào đối số tương ứng.



// Khởi tạo đối tượng
var sinhVien1 = new SinhVien("Ngô Minh Trung""Nam""B1704863""1999");

// Thiết lập lại giới tính
sinhVien1.setGioiTinh = "Nữ";

// Log ra giới tính hiện tại
console.log(sinhVien1.getGioiTinh);
 

Hiện tại, giới tính đã đổi từ Nam thành Nữ

> Lưu ý #1: JavaScript không hỗ trợ đầy đủ tính đóng gói trong Lập trình hướng đối tượng như Java, PHP hay Python. Vì thế, mọi thuộc tính đều có thể truy cập nếu bạn biết tên của thuộc tính đó (Giống như phạm vi truy cập public trong Java, tham khảo trong hướng dẫn: HỌC LẬP TRÌNH JAVA).

> Lưu ý #2: JavaScript nguyên bản thì không hỗ trợ private, protected nhưng bạn có thể mô phỏng chúng (Tuy nhiên sẽ hơi rắc rối đó)


4. Phương thức tĩnh (Static method)


Từ khóa static định nghĩa một phương thức static cho một lớp, còn được gọi là phương thức tĩnh.

Các phương thức tĩnh được gọi mà không cần khởi tạo lớp của chúng và không thể được gọi thông qua một đối tượng của lớp.

Phương thức tĩnh thường được sử dụng để tạo các chức năng tiện ích cho một ứng dụng.

Ví dụ:



class Point {
    constructor(xy) {
        this.x = x;
        this.y = y;
    }

    static distance(ab) {
        const dx = a.x - b.x;
        const dy = a.y - b.y;

        return Math.hypot(dxdy);
    }
}

const p1 = new Point(55);
const p2 = new Point(1010);
p1.distance//undefined
p2.distance//undefined

console.log(Point.distance(p1p2)); // 7.0710678118654755
 

Chúng ta không thể gọi hàm distance thông qua p1 hoặc p2. Mà phải gọi trực tiếp từ class của nó đó chính là Point.

5. Hoisting đối với class


Không giống như các hàm và các khai báo JavaScript khác, các khai báo class (lớp) không được hoisting.


var sinhVien1 = new SinhVien("Ngô Minh Trung");

class SinhVien {
    constructor(name) {
        this.hoTen = hoTen;
    }
}
 

Ví dụ trên sẽ tạo ra lỗi.

Để tránh lỗi, bạn phải khai báo một lớp trước khi bạn có thể sử dụng nó, như vậy:


class SinhVien {
    constructor(name) {
        this.hoTen = hoTen;
    }
}

var sinhVien1 = new SinhVien("Ngô Minh Trung");
 

6. Kế thừa class


JavaScript cũng hỗ trợ tính kế thừa (inheritance) như các ngôn ngữ khác, để tạo một lớp kế thừa, bạn sử dụng từ khóa extends.


class SinhVien extends ConNguoi {...}
 

Kế thừa cho chúng ta khả năng sử dụng lại code đã viết.

Sử dụng lại các thuộc tính và phương thức của một lớp có sẵn khi tạo một lớp mới giúp chúng ta tiết kiệm thời gian làm việc.

Một lớp được kế thừa từ lớp cha sẽ có tất cả tác phương thức từ lớp cha.

Ví dụ: Ta có một lớp ConNguoi và một lớp SinhVien được kế thừa từ lớp ConNguoi



class ConNguoi {
    constructor(hoTennamSinh) {
        this.hoTen = hoTen || "unknown";
        this.namSinh = namSinh || "unknown";
    }
    getHoTen() {
        return "Tên " + this.hoTen + ", sinh năm " + this.namSinh;
    }
}
class SinhVien extends ConNguoi {
    constructor(maSSVhoTennamSinh) {
        super(hoTennamSinh);
        this.maSSV = maSSV || "unknown";
    }
    getThongTin() {
        return this.getHoTen() + ", mã sinh viên " + this.maSSV;
    }
}
var sinhVien1 = new SinhVien("B1704863""Ngô Minh Trung""1999");
console.log(sinhVien1.getThongTin());
 

Kết quả:


Tên Ngô Minh Trung, sinh năm 1999, mã sinh viên B1704863
 

Qua đoạn code trên ta thấy:

  • Xuất hiện từ khóa super: Phương thức super() này là phương thức tham chiếu đến lớp cha. Khi chúng ta gọi phương thức super() trong hàm khởi tạo thì chúng ta gọi đến phương thức khởi tạo của lớp cha và có quyền truy cập đến các thuộc tính và phương thức khởi tạo của lớp cha.

  • Chúng ta cũng có thể gọi phương thức của lớp cha thông qua từ khóa super() khi chúng ta overwride phương thức đó.

Ví dụ:


class ConNguoi {
    constructor(hoTennamSinh) {
        this.hoTen = hoTen || "unknown";
        this.namSinh = namSinh || "unknown";
    }
    getThongTin() {
        return "tên " + this.hoTen + ", sinh năm " + this.namSinh;
    }
}
class SinhVien extends ConNguoi {
    constructor(maSSVhoTennamSinh) {
        super(hoTennamSinh);
        this.maSSV = maSSV || "unknown";
    }
    // Ghi đè phương thức
    getThongTin() {
        return (
            "MSSV " + this.maSSV + ", " + super.getThongTin()
        );
    }
}
var sinhVien1 = new SinhVien("B1704863""Ngô Minh Trung""1999");
console.log(sinhVien1.getThongTin());
 

Kết quả được như sau:


MSSV B1704863, tên Ngô Minh Trung, sinh năm 1999
 

Như vậy, ở class SinhVien mình đã ghi đè thành công phương thức getThongTin()

7. Từ khóa this trong class


Về từ khóa this thì thường bạn sẽ gặp trong các ngôn ngữ lập trình hướng đối tượng khác, nó là một thể hiện cho đối tượng đang chứa đoạn code đang được thực thi.

this thường được chỉ đến Object chứa phương thức đang được gọi thực thi.

Từ khóa this được mình sử dụng ở các phần trước.



class ConNguoi {
    constructor(hoTennamSinh) {
        this.hoTen = hoTen || "unknown";
        this.namSinh = namSinh || "unknown";
    }
    getThongTin() {
        return "Tên " + this.hoTen + ", sinh năm " + this.namSinh;
    }
}
 

Với class này mình sử dụng từ khóa this.<tên thuộc tính> 

Khi đoạn code được biên dịch thì hàm constructor() được gọi, thì sử dụng con trỏ this.hoTen và this.namSinh trong hàm contructor() được hiểu là class ConNguoi.

8. Kiểm tra loại đối tượng với instanceof


instanceof còn có tác dụng xác định xem đối tượng có phải là một thể hiện (đối tượng) của một class hay không.

Để mình ví dụ:



class ConNguoi {
    constructor(hoTennamSinh) {
        this.hoTen = hoTen || "unknown";
        this.namSinh = namSinh || "unknown";
    }
    getThongTin() {
        return "Tên " + this.hoTen + ", sinh năm " + this.namSinh;
    }
}

var sinhVien1 = new ConNguoi("Ngô Minh Trung""1999");
var sinhVien2 = {};

console.log(sinhVien1 instanceof ConNguoi); // true
console.log(sinhVien2 instanceof ConNguoi); // False
 


Như vậy ta sẽ thấy sinhVien1 là một thể hiện (đối tượng) của lớp ConNguoi, thế nên câu lệnh này trả về giá trị true.

Còn đối với sinhVien2 là đối tượng trống, thì không phải là thể hiện của ConNguoi nên nó sẽ là false.

instanceof còn có thể xác định là một thể hiện của lớp con có phải là một thể hiện của lớp cha.

Ví dụ:



class ConNguoi {
    constructor(hoTennamSinh) {
        this.hoTen = hoTen || "unknown";
        this.namSinh = namSinh || "unknown";
    }
    getHoTen() {
        return "Tên " + this.hoTen + ", sinh năm " + this.namSinh;
    }
}
class SinhVien extends ConNguoi {
    constructor(maSSVhoTennamSinh) {
        super(hoTennamSinh);
        this.maSSV = maSSV || "unknown";
    }
    getThongTin() {
        return this.getHoTen() + ", mã sinh viên " + this.maSSV;
    }
}
var sinhVien1 = new SinhVien("B1704863""Ngô Minh Trung""1999");

console.log(sinhVien1 instanceof SinhVien); // true
console.log(sinhVien1 instanceof ConNguoi); // true
 

Kết quả cả hai đều trả về true có nghĩa là sinhVien1 vừa là thể hiện của SinhVien và cũng là thể hiện của ConNguoi (lớp cha của SinhVien).

9. Class và prototypes


Cú pháp lớp (class) trong JavaScript thực hiện trừu tượng hóa các nguyên mẫu (prototypes) một cách tuyệt vời.

Các lớp được xây dựng từ việc kế thừa các nguyên mẫu. Mọi lớp đều được xem như là một hàm và tạo ra một thể hiện khi được gọi như một hàm tạo.

Chúng ta hãy so sánh hai đoạn mã sau nhé.

Đoạn code 1 sử dụng từ khóa class:



class ConNguoi {
    constructor(hoTennamSinh) {
        this.hoTen = hoTen || "unknown";
        this.namSinh = namSinh || "unknown";
    }
    getThongTin() {
        return "Tên " + this.hoTen + ", sinh năm " + this.namSinh;
    }
}
var sinhVien1 = new ConNguoi("Ngô Minh Trung"1999);
console.log(sinhVien1.getThongTin());
console.log(sinhVien1 instanceof ConNguoi);
 

Đoạn code thứ 2 sử dụng prototype (tương tự như tạo object ở bài trước)


function ConNguoi(hoTennamSinh) {
    this.hoTen = hoTen || "unknown";
    this.namSinh = namSinh || "unknown";
}

ConNguoi.prototype.getThongTin = function() {
    return "Tên " + this.hoTen + ", năm sinh" + this.namSinh;
}

var sinhVien1 = new ConNguoi("Ngô Minh Trung"1999);
console.log(sinhVien1.getThongTin());
console.log(sinhVien1 instanceof ConNguoi);
 

Đây là hai đoạn code tương đương với nhau. Đối với từ khóa class sẽ dễ sử dụng hơn nếu bạn đã quen với cách lập trình của ngôn ngữ Java hoặc C#.

Nếu bạn thích sử dụng từ khóa class hơn thì các bạn cũng nên hiểu rõ về kế thừa prototype nhé. Vì trong JavaScript prototype rất quan trọng.


Tổng kết


MÌnh vừa giới thiệu các bạn về class trong JavaSript đây chính là một điểm mới tránh các rườm rà của Object trước đây, class tường minh hơn sẽ dễ tiếp cận hơn.

Ngoài ra, mình cũng đã giới thiệu các bạn về một số khái niệm khác liên quan đến class trong JavaScript. Đây chỉ mới là một chút nền tảng cho các bạn học những thư viện hay framework của JavaScript về sau.


Hẹn gặp lại bạn ở bài học tiếp theo.


Bình luận Facebook
Đăng ký tư vấn
Nhân viên gọi điện tư vấn miễn phí sau khi đăng ký
Được cập nhật các ưu đãi sớm nhất
Hotline: 0383180086
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Hãy đăng ký để nhận những thông tin mới nhất về học bổng mới nhất tại NIIT - ICT Hà Nội
top
Đóng lại Đăng ký học tại NIIT - ICT Hà Nội
6260+ học viên đã theo học tại NIIT - ICT Hà Nội và có việc làm tốt trong ngành lập trình. Nắm lấy cơ hội ngay hôm nay!
Chọn khóa học
  • KHÓA HỌC LẬP TRÌNH FRONT END VỚI REACT.JS
  • KHÓA HỌC LẬP TRÌNH PHP WEB
  • Khóa học PHP Full stack [2023] cho người mới bắt đầu
  • Khóa học BIG DATA với Hadoop và Spark
  • Khóa học Lập trình Android tại Hà Nội
  • [Tuyển sinh 2023] Lập trình viên Quốc tế DigiNxt
  • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại Hà Nội
  • LẬP TRÌNH GAME
    • Khóa học Lập trình Game Unity
  • LẬP TRÌNH WEB FRONT END
    • KHÓA HỌC PYTHON HƯỚNG ĐỐI TƯỢNG
    • KHÓA HỌC ANGULAR & TYPESCRIPT (FRONT END)
  • LẬP TRÌNH WEB BACK END
    • LẬP TRÌNH JAVA WEB VỚI FRAME WORK
    • Lập trình Web với Django
    • Lập trình PHP với Laravel Framework
  • CHƯƠNG TRÌNH ĐÀO TẠO ỨNG DỤNG CÔNG NGHỆ
    • Khóa học Tiền lương & Phúc lợi (C&B Excel) tại TP HCM
  • LẬP TRÌNH WEB FULL STACK
    • Khóa học Java Full stack (IJFD)
  • LẬP TRÌNH MOBILE
    • FRONT-END VỚI REACTJS VÀ REACT NATIVE
    • Lập trình Android Nâng cao
  • ĐÀO TẠO CHO DOANH NGHIỆP
    • KHÓA HỌC BUSINESS ANALYSIC TỪ CƠ BẢN ĐẾN NÂNG CAO 2023
    • Khóa học Magento: Làm chủ CMS TMĐT lớn nhất
    • Khóa học IOT: Xây dựng Sản phẩm IOT với Raspberry Pi
    • Khóa học Automation Testing Chuyên nghiệp
  • KHÓA HỌC DỰ ÁN
    • Học sử dụng bộ Office: Word, Excel, Power Point, Mail chuyên nghiệp
  • KHÓA HỌC KHÁC
    • VBA Excel Toàn Tập (Cơ Bản - Nâng Cao)
    • VBA Excel Nâng cao
    • Khóa học JMeter: Performance Testing
    • Khóa học Tester đạt chuẩn Quốc tế ISTQB Foundation Level
    • Khoá Học Tester đạt chuẩn quốc tế ISTQB Advanced Level
Bạn chưa chọn khóa học cần đăng ký
Tên không được để trống
Số điện thoại không được để trống
Email không được để trống
Đăng ký học thành công!
Cảm ơn bạn đã đăng ký học tại NIIT - ICT HÀ NỘI!