命名空间是通过为项目或库创建一个全局对象,然后将所有的功能添加到该全局变量中。同时有效防止函数名、类名和其他人冲突。

在学习JavaScript命名空间模式之前,我们先来了解简单的命名空间。

简单的命名空间

由于JavaScript没有文件作用域,不同的函数分散在不同的文件中,甚至由不同的人编写,重名的概率大大增加。是不是足够小心就可以了呢?也不尽然,还有些意外情况,比如经常会用到继承,于是写了一个没出现过的函数名extend,不料在EcmaScript5中加入了extend函数,命名空间的必要性就体现出来了。
JavaScript有函数的作用域,可以利用这点把自定义的函数写到一个函数体内,这样函数内的变量、对象、函数就像在一个命名空间内一样和外部隔离。

1
2
3
4
5
6
7
8
9
<input type="button" value="test" onclick="(new namespace()).alert();"/>

<script type="text/javascript">
function namespace(){
this.alert=function(){
onsole.log('test');
}
}
</script>

这样自定义的alert方法就不会和window的alert冲突了。

每次调用的时候都要实例化对象,然后调用其方法,很麻烦,那我们可以这样简化,如下:

1
2
3
4
5
6
7
8
9
10
11
<input type="button" value="test" onclick="NS.alert();"/>

<script type="text/javascript">
(function namespace(){
this.alert=function(){
console.log('test');
}

window.NS=this;/*在自定义namespace函数最后把this赋值为window的NS属性,在调用的时候直接使用NS.xx就可以了。*/
})();
</script>

注:这里用到匿名函数,匿名函数是‘立即执行函数’

1
2
3
4
5
6
7
8
(function xxx(){
//function body
})();<!-- 最后的括号表示立即执行 ,可省略xxx -->
<!-- 等价于 -->
function xxx(){

}
xxx();

将匿名函数的方法定义到prototype中

1
2
3
4
5
6
7
8
9
10
11
(fucntion(){
var _NS=function(){

}

_NS.prototype.alert=function(){
console.log('test');
}

window.NS=new _NS();
})();

JavaScript创建命名空间

非常重要

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 编写一个namespace函数,要求此函数能够实现多层命名空间的嵌套
// 声明一个全局对象Namespace,用来注册命名空间
var Namespace = {};
// 全局对象仅仅存在register函数,参数为名称空间全路径,如"Grandsoft.GEA"
Namespace.register = function(fullPath) {
// 将命名空间切成N部分, 比如Grandsoft、GEA等
var sArray = fullPath.split('.');
var sEval = "";
var str = "";
for (var i = 0; i < sArray.length; i++) {
if (i != 0) str += ".";
str += sArray[i];
//依次创建构造命名空间对象(假如不存在的话)的语句,比如先创建Grandsoft,然后创建Grandsoft.GEA,依次下去
sEval += "if (typeof(" + str + ") == 'undefined') " + str + " = 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("Singapo91", 21);
p.show();