從事Web開發不可避免要接觸JavaScript,目前最新版本的JavaScript還是不支持命名空間,所以命名衝突的問題凸顯無疑,想象一下你引用了兩個js文件,卻發現由於命名問題導致你不得不放棄其中一個,從而導致多寫了許多代碼,無疑是十分令人沮喪的。在JavaScript新版本引入命名空間概念之前,發揚自立更生精神和創造性是我們程序員的基本義務;-)
實現前提:與Delphi、C#等語言不同,JavaScript中的類並不是對象的定義,事實上JavaScript中並不存在真正的類,這裏的類實際上是用函數模擬實現的,而JavaScript中的函數實際上是一個對象,因此在JavaScript中:一個類就是一個對象。這和傳統概念概念極爲不同,在JavaScript中,創建某個類的實例實際上就是將類(=對象,記住)複製了一份。看到這裏,有點設計模式概念的應該就可以看出來了,在JavaScript中,類機制使用了原型(prototype)模式。
實現原理:既然看清楚了類的本質,那麼問題就簡單了,如果將GEA項目組所有JS類和函數作爲屬性放在名爲GEA的對象裏面,然後將GEA對象以屬性的方式放在名爲Grandsoft對象裏面不就可以達到我們的目的,比如Grandsoft.GEA.Person實際上是在Grandsoft對象的屬性GEA(也是一個對象)中的類Person(還是一個對象)。
實現非常簡單,整個命名空間機制的實現不超過20行代碼,分析如下:
// 聲明一個全局對象Namespace,用來註冊命名空間
Namespace = new Object();
// 全局對象僅僅存在register函數,參數爲名稱空間全路徑,如"Grandsoft.GEA"
Namespace.register = function(fullNS)
{
// 將命名空間切成N部分, 比如Grandsoft、GEA等
var nsArray = fullNS.split('.');
var sEval = "";
var sNS = "";
for (var i = 0; i < nsArray.length; i++)
{
if (i != 0) sNS += ".";
sNS += nsArray[i];
// 依次創建構造命名空間對象(假如不存在的話)的語句
// 比如先創建Grandsoft,然後創建Grandsoft.GEA,依次下去
sEval += "if (typeof(" + sNS + ") == 'undefined') " + sNS + " = new Object();"
}
if (sEval != "") eval(sEval);
}
// 註冊命名空間Grandsoft.GEA, Grandsoft.GCM
Namespace.register("Grandsoft.GEA");
Namespace.register("Grandsoft.GCM");
// 在Grandsoft.GEA命名空間裏面聲明類Person
Grandsoft.GEA.Person = function(name, age)
{
this.name = name;
this.age = age;
}
// 給類Person添加一個公共方法show()
Grandsoft.GEA.Person.prototype.show = function()
{
alert(this.name + " is " + this.age + " years old!");
}
// 演示如何使用類Person
var p = new Grandsoft.GEA.Person("yanglf", 25);
p.show();
比較優秀的js framework都有命名空間的概念
var YAHOO = window.YAHOO || {};
YAHOO.namespace = function(ns) {
if (!ns || !ns.length) {
return null;
}
var levels = ns.split(".");
var nsobj = YAHOO;
// YAHOO is implied, so it is ignored if it is included
for (var i=(levels[0] == "YAHOO") ? 1 : 0; i<levels.length; ++i) {
nsobj[levels[i]] = nsobj[levels[i]] || {};
nsobj = nsobj[levels[i]];
}
return nsobj;
};
YAHOO.extend = function(subclass, superclass) {
var f = function() {};
f.prototype = superclass.prototype;
subclass.prototype = new f();
subclass.prototype.constructor = subclass;
subclass.superclass = superclass.prototype;
if (superclass.prototype.constructor == Object.prototype.constructor) {
superclass.prototype.constructor = superclass;
}
};
YAHOO.namespace("util");
YAHOO.namespace("widget");
YAHOO.namespace("example");