Ở tập trước, bạn đã học cách tạo class, khởi tạo mèo, cho nó kế thừa siêu năng lực bay lên trời. Nhưng cuộc đời đâu đơn giản vậy. Lập trình class cũng như nuôi mèo: càng chăm lâu, càng phát hiện ra nhiều... thứ.

Vấn đề tiếp theo: Có thứ không muốn ai biết – Private Fields

Tưởng tượng bạn có một con mèo biết nói tiếng người (kinh dị thật - hoặc không nếu tên của nó là Doraemon). Nhưng bạn không muốn ai khác ngoài bạn biết điều đó. Bạn thử làm thế này:

class Meo {
  constructor(ten) {
    this.ten = ten;
    this.biMat = 'Tôi đến từ tiểu vương quốc Bình Chánh 69';
  }
}

Người khác có thể dễ dàng đọc meo.biMat và phát hiện ra bí mật động trời. Không ổn. Bạn cần một cách để giấu thông tin. Và thế là…

Giải pháp: Trường riêng tư – Private Fields (kèm hashtag)

Người thông minh như bạn chắc chắn nghĩ ra rằng: “Làm sao để thông tin này không bị lộ?”. JavaScript 2019 (ES2022) bảo bạn: Dùng dấu #, không phải để bắt trend TikTok, mà để đánh dấu private field:

class Meo {
  #biMat;

  constructor(ten) {
    this.ten = ten;
    this.#biMat = 'Tôi đến từ tiểu vương quốc Bình Chánh 69';
  }

  tietLo() {
    console.log(`${this.ten} thì thầm: ${this.#biMat}`);
  }
}

const meoLa = new Meo('MeoLa');
meoLa.tietLo(); // MeoLa thì thầm: Tôi đến từ tiểu vương quốc Bình Chánh 69
console.log(meoLa.#biMat); // ❌ Báo lỗi ngay lập tức

Bạn thấy chưa? Với #, bí mật của mèo được giấu kỹ như mật mã hạt nhân. Không hacker nào truy cập được – trừ chính class.

Vấn đề: Class đang phình to như... mèo Tết

Giờ bạn có một method tietLo(). Ổn đấy. Nhưng rồi bạn lại cần thêm:

  • một method keu() cho mèo gào lúc nửa đêm,
  • một method giaiMaBiMat() để truy cập thông tin,
  • một xoaBiMat() để... xóa dấu vết,
  • một ghiNhoBiMat() để cập nhật dữ liệu...

Và bạn bắt đầu cảm thấy class của mình như ổ bánh mì thịt bị nhét quá nhiều topping: hành, chả, đồ chua, rau răm, ớt, pate, nước sốt – đến mức cắn một phát là trào ra hết 🤤.

Bạn thở dài:
"Không lẽ cứ nhồi hết vào class như nhét hành vào bánh mì vậy sao?"

Lý do: Bạn đang thiếu một lớp kiểm soát tinh tế

Bạn muốn người ta tương tác với mèo một cách có kiểm soát:

  • Ai được phép đọc bí mật?
  • Ai được phép chỉnh sửa thông tin?
  • Và chỉnh sửa thì phải theo điều kiện gì?

Câu trả lời chính là gettersetter – như một lễ tân chuyên nghiệp đứng canh cửa. Không ai được vào mà không xin phép, và muốn chỉnh gì thì cũng phải qua vòng kiểm duyệt.

Giải pháp: Dùng Getter & Setter như vệ sĩ thân tín

Thay vì tạo hàng loạt method rời rạc cho từng hành động, bạn tổ chức lại class bằng các thuộc tính private, và bao quanh bằng getter/setter để:

  • bảo vệ dữ liệu bên trong
  • gộp logic lại thành những “cổng” rõ ràng, dễ bảo trì
  • giúp code gọn gàng, sang-xịn-mịn
class Meo {
  #ten;

  constructor(ten) {
    this.#ten = ten;
  }

  // Getter – cho đọc
  get ten() {
    return this.#ten;
  }

  // Setter – cho chỉnh sửa, nhưng phải hợp lệ
  set ten(giaTriMoi) {
    if (giaTriMoi.length < 2) {
      console.log('Tên quá ngắn, mèo meo!');
    } else {
      this.#ten = giaTriMoi;
    }
  }
}

const luna = new Meo('Luna');
console.log(luna.ten); // Luna
luna.ten = 'A';        // Tên quá ngắn, mèo meo!
luna.ten = 'MewMew';   // Được rồi!
console.log(luna.ten); // MewMew

Vấn đề lớn nữa: Mỗi class một kiểu viết – vậy mẫu chuẩn là gì?

Bạn nhìn mấy class dài dằng dặc và hoang mang: “Có cần viết tất cả trong constructor không? Method để đâu? Có nên chia file? Làm sao giữ code đẹp trai như chính mình?”

Giải pháp: Một mẫu "Class có gu" – chuẩn chỉnh như quần tây áo sơ mi

class Meo {
  #ten;
  #tuoi;

  constructor(ten, tuoi) {
    this.#ten = ten;
    this.#tuoi = tuoi;
  }

  get ten() {
    return this.#ten;
  }

  set ten(tenMoi) {
    if (tenMoi.length >= 2) this.#ten = tenMoi;
  }

  gioiThieu() {
    console.log(`Xin chào, tôi là mèo ${this.#ten}, ${this.#tuoi} tuổi`);
  }

  // static method – dùng mà không cần tạo instance
  static meoNgau() {
    console.log('Mèo ngầu không cần giới thiệu 🐱‍👤');
  }
}

// Dùng thử
const boss = new Meo('Boss', 5);
boss.gioiThieu();      // Xin chào, tôi là mèo Boss, 5 tuổi
Meo.meoNgau();          // Mèo ngầu không cần giới thiệu 🐱‍👤

Tổng kết tập 2: Khi bạn không chỉ nuôi mèo – bạn xây dựng hệ sinh thái mèo

  • Dùng # để tạo thuộc tính riêng tư, như ổ khóa két sắt.
  • getset giúp bạn kiểm soát việc đọc/ghi dữ liệu – an toàn và linh hoạt.
  • static method là cách để tạo hành vi dùng chung mà không cần tạo object.
  • Một class “có gu” cần rõ ràng, dễ hiểu, không tham lam nhồi nhét.

Bạn thấy đấy, class trong JavaScript không chỉ là cú pháp – nó là một nghệ thuật. Và bạn – người viết class – là nghệ sĩ.

"Chào thân ái và quyết thắng"_duythenights