在小規模的腳本開發中,有時候並不值得去引用命名空間,由於會帶來某種程度的複雜性;可是當在同一個網頁裏引入10多個js文件以後,各js中的同 名函數就很容易衝突了。好比xxx庫裏寫了個addCssStyle方法,yyy類庫裏也寫了個addCssStyle方法,而這兩個方法的具體實現又有 必定差異。那麼同時引用這兩個組件的時候,函數衝突以後致使頁面效果發生變化,調試和修改都是很是痛苦的,若是爲了不衝突,而放棄引用一些優秀的組件, 那更是讓人鬱悶的事情。爲此,在封裝javascript組件庫的時候,請使用命名空間來避免衝突。將全部的方法和變量都要按包名類名的方式來寫。(這個 時候寫代碼的感受和封裝java的util方法同樣方便,呵呵)javascript
因此,請記住:請爲你封裝的JavaScript庫加上命名空間以提升代碼重用性。java
可是JavaScript原生並不支持命名空間,須要變通來實現。數組
在 JavaScript中,全部的對象(或者稱類型,例如Boolean,Array,Function)均可以認爲是一個關聯數組。關聯數組中的對象能夠 使用點(.)進行引用,這樣咱們能夠利用關聯數組變相地實現命名空間。首先聲明一個關聯數組做爲根,由於頁面聲明的對象都是window這個變量的成員, 因此通常命名空間的實現都以window爲根。當向window申請a.b.c的命名空間時,首先在window中查看是否存在a這個成員,若是沒有則在 window下新建一個名爲a的空關聯數組,若是已經存在a,則繼續在window.a中查看b是否存在,以此類推。下面分別是Atlas和YUI中的實 現方法。函數
//Atlas命名空間的實現方法工具
Function.registerNamespace =function(namespacePath){ui
//以window爲根this
var rootObject =window;編碼
//對命名空間路徑拆分紅數組spa
var namespaceParts =namespacePath.split('.');調試
for (var i =0;i <namespaceParts.length;i++) {
var currentPart =namespaceParts[i];
//若是當前命名空間下不存在,則新建一個Object對象,等效於一個關聯數組。
if (!rootObject[currentPart]) {
rootObject[currentPart]=new Object();
}
rootObject =rootObject[currentPart];
}
}
Atlas的實現通俗易懂。Javascrip中rootObject[currentPart]=new Object();和rootObject[currentPart]={};是等效的兩種寫法。
//YUI命名空間的實現方法
var YAHOO = window.YAHOO || {};
YAHOO.namespace = function(ns) {
if (!ns || !ns.length) {
return null;
}
var levels = ns.split(".");
var nsobj = YAHOO;
//若是申請的命名空間是在YAHOO下的,則必須忽略它,不然就成了YAHOO.YAHOO了
for (var i=(levels[0] == "YAHOO") ? 1 : 0; i<levels.length; ++i) {
//若是當前命名空間下不存在,則新建一個關聯數組。
nsobj[levels[i]] = nsobj[levels[i]] || {};
nsobj = nsobj[levels[i]];
}
//返回所申請命名空間的一個引用;
return nsobj;
};
YUI的實現帶有一點C風格,nsobj[levels[i]] = nsobj[levels[i]] || {};這句相比於Atlas顯得要晦澀一些。
比 較一下Atlas和YUI的實現,YUI稍微好一些,由於YUI中申請命名空間的時候會返回一個引用,能夠賦值給一個變量,這就至關於聲明瞭該名稱空間的 一個別名,編碼會方便很多。YUI把全部申請的命名空間都放在了window.YAHOO下面,這樣有什麼好處呢?假如Yahoo和其餘公司有合做關係, 須要嵌入對方的腳本時,這樣能保證它本身編寫的代碼都在YAHOO這個空間下面,而其餘公司不大可能在這個空間下面編碼,就基本不會出現命名衝突的狀況。 我以爲這個作法好,是由於在不對等的合做關係中,要求對方去修改代碼來適應你的應用是不現實的,YUI的實現考慮了這點。
還有一點,全部的 命名空間都放在window.YAHOO下是最好最合理的作法嘛?在大量應用動態效果的頁面中,這勢必要維護一個超大的關聯數組。關聯數組本質是哈希數 組,檢索數組成員的開銷能夠忽略不計,可是window.YAHOO承載的東西太多太複雜,這是否違背了大道至簡的原則?有沒有更好的辦法?
例子:
//一、命名空間註冊工具類
var Namespace = new Object();
Namespace.register = function(path) {
var arr = path.split(".");
var ns = "";
for ( var i = 0; i < arr.length; i++) {
if (i > 0)
ns += ".";
ns += arr[i];
eval("if(typeof(" + ns + ") == 'undefined') " + ns + " = new Object();");
}
}
//二、註冊命名空間 com.cjm.ui
Namespace.register("com.cjm.ui");
//三、使用命名空間
com.cjm.ui.TreeGrid = function() {
this.sayHello = function(name) {
alert("Hello " + name);
}
}
var t = new com.cjm.ui.TreeGrid();t.sayHello("uid");