Trong JavaScript, do đặc thù của ngôn ngữ, không có cơ chế hỗ trợ biến private (riêng tư) sẵn có như trong các ngôn ngữ lập trình hướng đối tượng khác (ví dụ: Java, C++). Tuy nhiên, bằng việc áp dụng một số kỹ thuật và mẫu thiết kế, chúng ta có thể tạo ra hiệu ứng tương tự biến private. Điều này không chỉ giúp tăng cường bảo mật cho mã nguồn mà còn thể hiện sự hiểu biết sâu sắc về JavaScript khi đi phỏng vấn.
Khái niệm biến Private
Trong lập trình hướng đối tượng, biến private là những biến chỉ có thể được truy cập từ bên trong các phương thức của lớp. Chúng thường được dùng để lưu trữ dữ liệu nhạy cảm hoặc phục vụ logic nội bộ mà không muốn người dùng bên ngoài tùy ý thay đổi hay truy cập.
Các phương pháp mô phỏng biến Private trong JavaScript
1. Sử dụng Closure (Bao đóng)
Closure là một khái niệm quan trọng trong JavaScript, cho phép một hàm có thể truy cập các biến từ phạm vi bên ngoài của nó, ngay cả khi hàm đó được gọi bên ngoài phạm vi đó. Tận dụng closure, chúng ta có thể tạo ra các biến "private" chỉ có thể được truy cập bởi một hàm cụ thể.
function taoBoDem() {
// Biến private
let soLuong = 0;
// Trả về một đối tượng chứa các phương thức có thể truy cập biến private
return {
tangLen: function() {
soLuong++;
return soLuong;
},
giamXuong: function() {
soLuong--;
return soLuong;
},
laySoLuong: function() {
return soLuong;
}
};
}
// Khởi tạo một đối tượng bộ đếm
const boDem = taoBoDem();
console.log(boDem.laySoLuong()); // Kết quả: 0
console.log(boDem.tangLen()); // Kết quả: 1
console.log(boDem.tangLen()); // Kết quả: 2
console.log(boDem.giamXuong()); // Kết quả: 1
// Không thể truy cập trực tiếp biến private 'soLuong'
// console.log(boDem.soLuong); // Kết quả: undefined
Trong ví dụ trên, soLuong là một biến private, chỉ có thể được truy cập và thay đổi thông qua các phương thức của đối tượng được trả về từ hàm taoBoDem. Mã nguồn bên ngoài không thể truy cập trực tiếp biến soLuong.
2. Sử dụng ES6 Class và Symbol
Mặc dù cú pháp class đã được giới thiệu trong ES6, nhưng nó không thực sự hỗ trợ biến private. Tuy nhiên, chúng ta có thể sử dụng Symbol để tạo ra các thuộc tính khó bị truy cập từ bên ngoài, từ đó mô phỏng hiệu ứng của biến private.
const THUOC_TINH_RIENG_SO_LUONG = Symbol('soLuong');
class BoDem {
constructor() {
// Sử dụng Symbol để tạo thuộc tính khó truy cập từ bên ngoài
this[THUOC_TINH_RIENG_SO_LUONG] = 0;
}
tangLen() {
this[THUOC_TINH_RIENG_SO_LUONG]++;
return this[THUOC_TINH_RIENG_SO_LUONG];
}
giamXuong() {
this[THUOC_TINH_RIENG_SO_LUONG]--;
return this[THUOC_TINH_RIENG_SO_LUONG];
}
laySoLuong() {
return this[THUOC_TINH_RIENG_SO_LUONG];
}
}
// Khởi tạo một đối tượng bộ đếm
const boDem = new BoDem();
console.log(boDem.laySoLuong()); // Kết quả: 0
console.log(boDem.tangLen()); // Kết quả: 1
console.log(boDem.tangLen()); // Kết quả: 2
console.log(boDem.giamXuong()); // Kết quả: 1
// Cố gắng truy cập biến private (về mặt kỹ thuật không phải private thực sự, nhưng khó đoán từ bên ngoài)
// console.log(boDem.soLuong); // Kết quả: undefined
// console.log(boDem['soLuong']); // Kết quả: undefined
// console.log(boDem[THUOC_TINH_RIENG_SO_LUONG]); // Lỗi: THUOC_TINH_RIENG_SO_LUONG không khả dụng trong phạm vi bên ngoài
Ở ví dụ này, chúng ta dùng Symbol để tạo một định danh duy nhất THUOC_TINH_RIENG_SO_LUONG và sử dụng nó làm tên thuộc tính của đối tượng. Do tính duy nhất của Symbol, mã nguồn bên ngoài rất khó để đoán được tên thuộc tính này, do đó tạo ra hiệu ứng của biến private. Tuy nhiên, đây không phải là private thực sự, vì vẫn có thể truy cập các thuộc tính này thông qua một số phương thức (ví dụ: API phản xạ hoặc liệt kê thuộc tính của đối tượng). Nhưng trong hầu hết các trường hợp, phương pháp này đủ an toàn.
Tổng kết
Việc mô phỏng biến private trong JavaScript đòi hỏi một số kỹ thuật bổ sung, nhưng bằng cách sử dụng closure và Symbol, chúng ta có thể đạt được hiệu quả tương tự. Những kỹ thuật này không chỉ giúp tăng cường bảo mật mã nguồn mà còn là cơ hội để thể hiện sự hiểu biết sâu sắc về JavaScript trong các buổi phỏng vấn. Dù bạn là người mới bắt đầu hay là một nhà phát triển có kinh nghiệm, việc nắm vững các kỹ thuật này sẽ có tác động tích cực đến kỹ năng lập trình của bạn.