js的命名空間

在小規模的腳本開發中,有時候並不值得去引用命名空間,由於會帶來某種程度的複雜性;可是當在同一個網頁裏引入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");

相關文章
相關標籤/搜索