三维GIS交流 WorldWind GoogleEarth EV-Globe osgearth


               积沙成塔,集腋成裘,千里之行,积于跬步。夏丏尊有联:贵有恒,何必三更起五更睡;最无益,只怕一日曝十日寒。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

在JavaScript中实现命名空间

注:好久没写了,今天把我在公司内网写的文章拷一份,出来露露脸,刚转Web开发,所以开始学JavaScript!

在引入命名空间之前,一个令开发人员头疼的问题就是如何防止函数名/类名和其他人的冲突,在一个公司内部项目组之间可以通过命名预定(比如加前缀等)解决这个问题,但是把视线放到整个软件开发领域,在当今协作开发相当盛行的时代,这个问题却依然存在。在使用多个第三方框架或类库的时候,你唯一能作的就是祈祷它们的命名不要冲突,如果真正发生这种灾难的话,你唯一能作的就是放弃其中一个(注:可能是我孤陋寡闻,呵呵)。命名空间的引入相当程度上解决了这个问题,当然,如果你使用的命名空间和其他公司不幸一样,而对方又是微软、SUN等大佬,那恭喜你,呵呵@_@!

从事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);
}

上面就是在JavaScript中模拟命名空间机制的完整实现,使用方式如下:

// 注册命名空间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();

哈哈,简单吧,这么简单的代码我就不多说了,大家自己看着玩吧,其实我有点懒,呵呵@_@!!!

posted on 2006-10-11 18:17 游民一族 阅读(435) 评论(16)  编辑 收藏 引用 收藏至365Key

评论

# re: [原创]在JavaScript中实现命名空间 2006-10-11 18:32 eden

这可不是一般的冷饭。。。  回复   

# re: [原创]在JavaScript中实现命名空间 2006-10-11 18:38 游民一族

呵呵,体谅一下,刚开始学JS嘛  回复   

# re: [原创]在JavaScript中实现命名空间 2006-10-11 18:39 还是匿了吧

无言  回复   

# re: [原创]在JavaScript中实现命名空间 2006-10-11 18:45 游民一族

这种实现网上有很多了么?我想了好几个小时才有思路并实现出来的,太伤心了  回复   

# re: 在JavaScript中实现命名空间 2006-10-11 19:58 真无语。。。

呵呵,能把自己东西共享出来,还是鼓励下吧。
不过真的是。。。还是不说好了,,呵呵
  回复   

# re: 在JavaScript中实现命名空间 2006-10-11 20:01 游民一族

哈哈,看来真的是一大盆冷饭,不过我在网上找咋就找不到类似的实现呢?莫非我的关键字选的有问题么?  回复   

# re: 在JavaScript中实现命名空间 2006-10-11 20:12 游民一族

嘿,还真找到一个(http://blog.sina.com.cn/u/493d4751010003o0),不过写得和我不一样,而且也没我这个好玩吧?!  回复   

# re: 在JavaScript中实现命名空间 2006-10-11 20:23 真无语。。。

去看看atlas的js库都有。晕哦。楼主好孤漏  回复   

# re: 在JavaScript中实现命名空间 2006-10-11 20:28 游民一族

哈哈,看了一下atlas,用法居然和我差不多,不过不知道它是怎么实现的,没看到源码,看来我果然是天才(开个玩笑,嘿嘿)。  回复   

# re: 在JavaScript中实现命名空间 2006-10-11 20:33 游民一族

大家可以到这里看看Atlas的命名空间的使用方式:
http://blog.cdbook.cn/user1/atlas/archives/2006/2006925164154.html

-> 以前用“JAVASCRIPT + 命名空间”一个都找不到,刚才用“ATLAS+命名空间”搜出一堆,不过好像都是Atlas里面的
-> 大家如果有好的相关的资源,希望贴出来大家学习学习
-> 还有,除了说冷饭之外,大家也帮忙提出一点建设性的意见,看有没有更优美的方式  回复   

# re: 在JavaScript中实现命名空间 2006-10-11 20:47 Jeffrey Zhao

哎,说句实话……JS里实现Namespace……的确没有什么好说的,很容易想到的做法。可能楼主的确接触JS的时间不长吧……  回复   

# re: 在JavaScript中实现命名空间 2006-10-11 21:31 游民一族

好吧,我承认我是个土人,看电视睡觉去喽,呵呵@_@!!!  回复   

# re: 在JavaScript中实现命名空间 2006-10-12 08:50 浪子

也可以看下yui的命名空间方式,还有prototype
比较优秀的js framework都有命名空间的概念
 
yui的命名空间和继承机制

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");
  回复   

 

# re: 在JavaScript中实现命名空间 2006-10-12 09:07 robinhood

楼主的实现挺好的

我个人的实现方式还是直接创造对象来实现命名空间的

楼主的实现和Yahoo UI中的实现差不多

多多交流!  回复   

# re: 在JavaScript中实现命名空间 2006-10-12 09:13 游民一族

@浪子
谢谢,不过目前不想使用任何framework,因为我是想学javascript而不是学习怎么使用某个框架,等把基础打好了,以后需要做东西的时候再用XX框架也不迟。
参考人家优秀的代码确实是个学习的捷径,不过我有个毛病,看多了别人的东西后自己的思路就会受到影响,呵呵,典型的意志不坚定分子,再次感谢  回复   

# re: 在JavaScript中实现命名空间 2006-10-12 09:30 萧远山

研究精神值得鼓励,加油!  回复

网址:http://www.cnblogs.com/leafyoung/archive/2006/10/11/526570.html?Pending=true#Post

posted on 2006-10-12 09:50  niceboy  阅读(284)  评论(0编辑  收藏  举报
点击这里给我发消息