Module Design Pattern là một mẫu thiết kế (design pattern) phổ biến trong JavaScript, giúp tổ chức mã theo từng module riêng biệt. Mục tiêu chính của mẫu này là tạo ra một không gian riêng biệt cho mỗi module, giúp tránh xung đột giữa các biến và hàm (encapsulation), đồng thời cung cấp khả năng chia sẻ và tái sử dụng mã tốt hơn. Đây là cách để tạo ra các thành phần (components) dễ bảo trì, dễ mở rộng và có cấu trúc rõ ràng.
Một cách phổ biến để triển khai module pattern trong JavaScript là sử dụng IIFE (hàm được gọi ngay lập tức). Điều này giúp tạo ra một không gian biệt lập cho các biến và hàm trong module, tránh việc chúng “rò rỉ” ra phạm vi toàn cục.
Ví dụ:
const myModule = (function() { // Biến và hàm private let privateVar = 'Tôi là một biến private'; function privateMethod() { console.log('Tôi là một hàm private'); } // Biến và hàm public (được return ra ngoài) return { publicVar: 'Tôi là một biến public', publicMethod: function() { console.log('Tôi là một hàm public'); privateMethod(); } }; })(); // Sử dụng module console.log(myModule.publicVar); // Tôi là một biến public myModule.publicMethod(); // Tôi là một hàm public // Không thể truy cập vào biến hoặc hàm private console.log(myModule.privateVar); // undefined myModule.privateMethod(); // Error: myModule.privateMethod is not a function
Trong ví dụ trên:
privateVar
và privateMethod
là các phần tử “private”, chỉ có thể truy cập bên trong module.publicVar
và publicMethod
là các phần tử “public”, có thể truy cập từ bên ngoài module.privateMethod
chỉ có thể được gọi thông qua publicMethod
, tạo ra sự bao đóng (encapsulation).Revealing Module Pattern là một biến thể của module pattern, trong đó chúng ta định nghĩa tất cả các biến và hàm ở bên trong module, sau đó chỉ định rõ những gì sẽ được “lộ” (revealed) ra bên ngoài, tức là những thành phần nào sẽ trở thành public.
Ví dụ:
const myRevealingModule = (function() { let privateVar = 'Tôi là một biến private'; function privateMethod() { console.log('Tôi là một hàm private'); } function publicMethod() { console.log('Tôi là một hàm public'); privateMethod(); } function publicVarMethod() { return privateVar; } // Chỉ tiết lộ những gì muốn public return { publicMethod: publicMethod, publicVarMethod: publicVarMethod }; })(); // Sử dụng module myRevealingModule.publicMethod(); // Tôi là một hàm public console.log(myRevealingModule.publicVarMethod()); // Tôi là một biến private
Revealing Module Pattern giúp mã nguồn dễ hiểu hơn vì tất cả các phương thức và thuộc tính đều được định nghĩa trước khi chúng được “tiết lộ” ra ngoài. Điều này giúp dễ dàng quản lý các phần private và public.
Với sự xuất hiện của ECMAScript 6 (ES6), JavaScript đã hỗ trợ mô-đun hóa natively bằng cách sử dụng từ khóa import
và export
. Điều này cung cấp một cách chuẩn hóa hơn để tổ chức mã thành các module mà không cần sử dụng IIFE.
Ví dụ:
// module.js export const publicVar = 'Tôi là một biến public'; export function publicMethod() { console.log('Tôi là một hàm public'); } // main.js import { publicVar, publicMethod } from './module.js'; console.log(publicVar); // Tôi là một biến public publicMethod(); // Tôi là một hàm public
Trong ES6:
export
cho phép chúng ta “lộ” ra các biến, hàm, hoặc lớp từ một module.import
cho phép chúng ta lấy các phần tử đã được export từ module khác để sử dụng.Module Design Pattern là một mẫu thiết kế mạnh mẽ và hữu ích trong JavaScript, giúp phân chia mã thành các phần độc lập, dễ bảo trì và mở rộng. Với sự xuất hiện của ES6, module pattern trở nên rõ ràng và chuẩn hóa hơn, giúp lập trình viên quản lý các thành phần của ứng dụng một cách dễ dàng và có cấu trúc hơn.