JavaScript 全局變量污染與命名衝突是大型項目的頭號隱患。命名空間模式通過「一個全局對象承載所有模塊」解決此問題。本文對比 5 種主流寫法,從結構、封裝性、壓縮友好度、調用便利性多維度分析,助你選型。
var sayHello = function() { return 'Hello var'; };
function sayHello(name) { return 'Hello function'; }
sayHello(); // 輸出 "Hello var" —— 函數聲明被提前,變量聲明提前但賦值不提前,最終 var 覆蓋 function
**結論**:始終使用 `var/let/const` 聲明函數表達式,避免函數聲明提前帶來的不可預期行為。
var NS = NS || {};
NS.Hello = function() {
this.name = 'world';
};
NS.Hello.prototype.sayHello = function(_name) {
return 'Hello ' + (_name || this.name);
};
var hello = new NS.Hello();
hello.sayHello(); // "Hello world"
var NS = NS || {};
NS.Hello = {
name: 'world',
sayHello: function(_name) {
return 'Hello ' + (_name || this.name);
}
};
NS.Hello.sayHello('JS'); // "Hello JS" —— 無需實例化,直接調用
var NS = NS || {};
NS.Hello = (function() {
var self = {}; // 公共接口對象
var name = 'world'; // 私有變量
self.sayHello = function(_name) {
return 'Hello ' + (_name || name); // 訪問私有變量
};
return self; // 暴露公共接口
})();
NS.Hello.sayHello(); // "Hello world"
var NS = NS || {};
NS.Hello = (function() {
var name = 'world';
var sayHello = function(_name) {
return 'Hello ' + (_name || name); // 內部直接調用 sayHello()
};
return {
sayHello: sayHello // 只暴露需要的公共接口
};
})();
var NS = NS || {};
NS.Hello = new function() {
var self = this;
var name = 'world';
self.sayHello = function(_name) {
return 'Hello ' + (_name || name);
};
};
NS.Hello.sayHello('JS'); // "Hello JS" —— 直接調用,無需 new
| 維度 | 1.構造器 | 2.JSON字面量 | 3.閉包+對象 | 4.閉包改進 | 5.new function |
|---|---|---|---|---|---|
| 私有成員 | ❌ | ❌ | ✅ | ✅ | ❌ |
| 內部調用便利性 | this. | this. | self. / 直接 | 直接 | self. |
| 壓縮友好度 | 中 | 高 | 高 | 高 | 高 |
| 調用方式 | new 實例化 | 直接 | 直接 | 直接 | 直接 |
| 推薦場景 | 需繼承/多實例 | 簡單單例、工具庫 | 需私有狀態的模塊 | **通用首選** | 偏好 this 風格團隊 |
掌握這 5 種模式,既能維護舊代碼,也能在無構建環境下快速搭建模塊化架構。