JS không có namespace gốc — mọi biến/function toàn cục cùng chung window (browser) hoặc global (Node). Nạp nhiều file JS dễ gây name collision (trùng tên).
Vấn đề: Name Collision
// TeamA1.js
function Student(fname, lname) { this.fname = fname; this.lname = lname; }
// TeamA2.js (nạp sau)
function Student(fname, mname, lname) {
this.fname = fname; this.mname = mname; this.lname = lname;
}
// HTML nạp cả hai
new Student('Raj', 'Prasad'); // Gọi TeamA2.Student → mname = undefined
// Output: "Raj undefined Prasad" — sai logic!
Giải pháp: Namespace Pattern với Object
Dùng object làm container — "namespace" thủ công.
Pattern cơ bản
var MyApp = MyApp || {}; // Nếu đã có thì dùng, chưa có thì tạo mới
Nested Namespace
var MyApp = MyApp || {};
MyApp.TeamA1 = MyApp.TeamA1 || {};
MyApp.TeamA2 = MyApp.TeamA2 || {};
Triển khai thực tế
TeamA1.js
var Tutorix = Tutorix || {};
Tutorix.TeamA1 = Tutorix.TeamA1 || {};
Tutorix.TeamA1.Student = function(fname, lname) {
this.fname = fname;
this.lname = lname;
this.getFullName = function() {
return this.fname + ' ' + this.lname;
};
return this;
};
TeamA2.js
var Tutorix = Tutorix || {};
Tutorix.TeamA2 = Tutorix.TeamA2 || {};
Tutorix.TeamA2.Student = function(fname, mname, lname) {
this.fname = fname;
this.mname = mname;
this.lname = lname;
this.getFullName = function() {
return this.fname + ' ' + this.mname + ' ' + this.lname;
};
return this;
};
HTML sử dụng
<script src="TeamA1.js"></script>
<script src="TeamA2.js"></script>
<script>
document.write(Tutorix.TeamA1.Student('Rajendra', 'Prasad').getFullName()); // Rajendra Prasad
document.write('<br>');
document.write(Tutorix.TeamA2.Student('Babu', 'Rajendra', 'Prasad').getFullName()); // Babu Rajendra Prasad
</script>
Kết quả
Rajendra Prasad Babu Rajendra Prasad
Các pattern nâng cao
IIFE (Immediately Invoked Function Expression) — Private scope
var MyModule = (function() {
let privateVar = 'secret';
function privateFn() { ... }
return {
publicMethod: function() { ... }
};
})();
ES6 Modules (Khuyên dùng cho project hiện đại)
// math.js
export const PI = 3.14;
export function add(a, b) { return a + b; }
// main.js
import { add, PI } from './math.js';
Tóm tắt
| Cách | Ưu điểm | Nhược điểm | Phù hợp |
|---|---|---|---|
| Global object namespace | Đơn giản, chạy mọi nơi | Vẫn global, có thể ghi đè | Project nhỏ, legacy |
| IIFE Module Pattern | Private scope, encapsulation | Hand-crafted, không tree-shake | Library, plugin |
| ES6 Modules | Chuẩn, static analysis, tree-shaking, scoped | Cần bundler/server hỗ trợ | Project hiện đại |