0
0
Lập trình
Hưng Nguyễn Xuân 1
Hưng Nguyễn Xuân 1xuanhungptithcm

Sử dụng Proxy để Tạo Đối Tượng JavaScript Bất Biến

Đăng vào 1 ngày trước

• 4 phút đọc

Sử dụng Proxy để Tạo Đối Tượng JavaScript Bất Biến

JavaScript là một ngôn ngữ lập trình mạnh mẽ, nhưng các đối tượng trong JavaScript lại có tính biến đổi.
Điều này có thể dẫn đến những lỗi không mong muốn khi có những thay đổi bất ngờ xảy ra trên các cấu trúc dữ liệu mà lẽ ra phải giữ nguyên.

👉 Vậy nếu chúng ta có thể đảm bảo tính bất biến một cách nội tại, mà không cần đến thư viện bên ngoài thì sao?
Chính lúc này, Proxy xuất hiện như một giải pháp hữu hiệu.


🔍 Tại Sao Tính Bất Biến Quan Trọng

Tính bất biến mang lại nhiều lợi ích:

  • Dễ dự đoán: Dữ liệu của bạn sẽ không bị thay đổi một cách ngẫu nhiên.
  • Dễ dàng gỡ lỗi: Không có những thay đổi trạng thái "ẩn".
  • Phù hợp với lập trình hàm: Tương thích tốt với React, Redux, và các phương pháp quản lý trạng thái khác.

Thông thường, để có được tính bất biến, lập trình viên thường cần đến các thư viện như Immutable.js hoặc sử dụng Object.freeze.
Tuy nhiên, Object.freeze chỉ hoạt động ở mức độ nông — nó chỉ ngăn cản các thay đổi ở cấp độ cao nhất, mà không bảo vệ các thuộc tính lồng nhau.
Chính vì vậy, Proxy trở thành một lựa chọn tuyệt vời ✨.


🛠 Sử Dụng Proxy Để Đảm Bảo Tính Bất Biến

Đối tượng Proxy cho phép chúng ta chặn các thao tác được thực hiện trên một đối tượng.
Chúng ta có thể "bẫy" các thao tác thay đổi và ngăn chặn chúng.

javascript Copy
function immutable(obj) {
  return new Proxy(obj, {
    set(target, prop, value) {
      throw new Error(`❌ Không thể thay đổi thuộc tính "${prop}". Đối tượng là bất biến.`);
    },
    deleteProperty(target, prop) {
      throw new Error(`❌ Không thể xóa thuộc tính "${prop}". Đối tượng là bất biến.`);
    },
    defineProperty(target, prop, descriptor) {
      throw new Error(`❌ Không thể định nghĩa lại thuộc tính "${prop}". Đối tượng là bất biến.`);
    }
  });
}

✅ Ví Dụ Thực Tế

javascript Copy
const user = immutable({
  name: "Rudy",
  role: "Kỹ sư Frontend",
  skills: ["Angular", "TypeScript"]
});

console.log(user.name); // Rudy

user.name = "John"; 
// ❌ Lỗi: Không thể thay đổi thuộc tính "name". Đối tượng là bất biến.

delete user.role; 
// ❌ Lỗi: Không thể xóa thuộc tính "role". Đối tượng là bất biến.

🔁 Bất Biến Sâu

Mã ở trên chỉ hoạt động với các thuộc tính cấp cao.
Nhưng nếu chúng ta muốn các đối tượng lồng nhau cũng bất biến thì sao?
Chúng ta có thể bao bọc chúng một cách đệ quy trong một proxy:

javascript Copy
function deepImmutable(obj) {
  if (obj !== null && typeof obj === "object") {
    return new Proxy(obj, {
      get(target, prop) {
        return deepImmutable(target[prop]);
      },
      set() {
        throw new Error("❌ Không thể thay đổi đối tượng bất biến.");
      },
      deleteProperty() {
        throw new Error("❌ Không thể xóa thuộc tính.");
      }
    });
  }
  return obj;
}

Sử dụng:

javascript Copy
const config = deepImmutable({
  app: {
    theme: "dark",
    version: "1.0"
  }
});

console.log(config.app.theme); // dark

config.app.theme = "light"; 
// ❌ Lỗi: Không thể thay đổi đối tượng bất biến.

🚀 Khi Nào Nên Sử Dụng

  • Quản lý trạng thái: Ngăn chặn thay đổi không mong muốn trong các ứng dụng sử dụng React/Redux/NgRx.
  • Dữ liệu chia sẻ: Khi nhiều lập trình viên làm việc với cùng một cấu trúc, tính bất biến giúp tránh xung đột.
  • API: Khi trả về các đối tượng, đảm bảo tính bất biến giúp tránh việc người tiêu dùng phá vỡ các hợp đồng dữ liệu.

⚖️ Đánh Giá Các Trade-off

  • Có một chi phí hiệu năng nhẹ do việc bao bọc bằng Proxy.
  • Có thể không cần thiết cho các dự án nhỏ, nơi mà kỷ luật là đủ.
  • Proxy không được hỗ trợ trong các môi trường cũ (nhưng hoạt động tốt trong tất cả các trình duyệt hiện đại và Node.js).

🎯 Kết Luận

Tính bất biến là một khái niệm mạnh mẽ giúp giảm thiểu lỗi và làm cho việc lý giải mã của bạn dễ dàng hơn rất nhiều.
Với Proxy, JavaScript cung cấp cho chúng ta một cách tiếp cận nội tại để đảm bảo tính bất biến mà không cần thư viện bên thứ ba.

Lần tới khi bạn muốn các đối tượng an toàn, hãy thử bao bọc chúng bằng một Proxy — và làm cho trạng thái của bạn trở nên an toàn hơn từ thiết kế.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào