標籤:
JS編程中我們可能會遇到命名衝突的問題。命名衝突分兩種情況來處理,對於模組內部,我們通常建立命名空間來解決;對於不同架構類庫,我們採用無衝突處理(多庫共存)的手段解決。
1.模組內部,註冊命名空間
一個大模組可以細分成若干小模組,命名空間其實就是在大模組的範圍裡面聲明小的範圍,這樣不同範圍之間同名標識符互不影響。
1)用立即執行函數運算式(IIFE)作為範圍。
var a = 1;(function() { var a = 2; console.log(a);//2})();console.log(a);//1
IIFE內部想調用外部的同名變數,可以將外部同名變數當參數傳進去,但是外部想調用IIFE範圍裡的變數卻不方便了。
2)對象字面量方式建立命名空間。
對象字面量{}括起來的就是一個範圍,我們通常聲明一個對象字面量,然後用“.”的方式給它建立若干屬性正是這種原理。
var Lxt = { A : {}, B : {}};Lxt.A.a = 1;Lxt.B.a = 2;console.log(Lxt.A.a);//1console.log(Lxt.B.a);//2
A範圍裡的a與B範圍裡的a互不干擾,這就是對象字面量方式建立命名空間。
3)使用註冊函數建立命名空間。
註冊函數是上面那種方式的加強版,上面那個例子如果沒事先定義A和B,則下面的Lxt.A.a會報錯,註冊函數其實就是將定義空間的過程封裝了起來。
var Lxt = {};var namespace = function(scope, space) { var spaces = space.split("."); var currentScope = scope; for(var i = 0, len = spaces.length; i < len; i++) { if(!currentScope[spaces[i]]) { currentScope[spaces[i]] = {}; } currentScope = currentScope[spaces[i]]; }}; namespace(Lxt, "A"); namespace(Lxt, "B");
得到的結果同2)中聲明的Lxt一樣。
2.不同類庫無衝突處理
無衝突處理的原理很簡單,類庫載入前儲存衝突命名,類庫載入後再將衝突命名重新賦值回去。
拿“$”來舉例,我在$1.js中聲明一個全域變數“$”,在$2.js中也聲明一個全域變數“$”,先載入$1,之後馬上載入$2,調用時“$”則不會指向$1的$內容了。
//$1.js:var $ = J = { test : function() { return "from $1.js..."; }};
//$2.js:var $ = K = { test : function() { return "from $2.js..."; }};
頁面先後引入$1.js與$2.js後測試發現,訪問不了$1的test函數了。
console.log($.test());//from $2.js...
那麼無衝突怎麼處理呢?拿$2來舉例,在$2代碼最前面儲存“$”,這時,變數儲存了$1的內容,模仿JQuery的noConflict函數,調用該函數的時候將儲存的變數重新賦給“$”。最終效果是“$”指向“$1”的內容。
//$2.jsvar _$ = window.$;var $ = K = { test : function() { return "from $2.js..."; }, noConflict : function() { window.$ = _$; return K; }};
測試結果如下:
$.noConflict();console.log($.test());//from $1.js...
命名空間與無衝突處理