1什么是单体
单体是javascript中最基本但是又是最有用的模式之一,它可以将代码组织为一个逻辑单元,这个逻辑单元的代码可以通过单一的变量进行访问。通过确保单体对象只存在一份实例,你就可以确信自己的所有代码使用的同样的全局资源,最简单的单体实际就是一个对象字面量。
var Signletion = {
attribute1: true,
attribute2: 10,
method1: function() {},
method2: function() {}
}
你可能没有发觉这种单体对象与普通字面量有什么不同,按照传统定义,单体是一个只能被实例化一次并且可以通过一个众所周知的访问点访问的类。要是严格地的按照这个定义来说,前面的例子所展示的并不是一个单体,应为它是一个不可被实例化的类。这里我们把单体定义的更为广义一些:单体是一个用来划分命名空间并将一批方法和属性组织在一起的对象,如果它可以被实例化,那它只能被实例化一次。
2.1划分命名空间
单体对象由两个组成部分:包含着方法和属性成员的对象自身,以及用于访问它的变量。
在这里说下本人在项目中避免变量冲突的方法,一般在项目中定义变量都没有用命名空间的习惯,都是在变量加自己名字的后缀。
function findProduct(id){
....
}
//同项目 成员 的代码
var resetProduct = $('reset-product');
var findProduct = $('find-product');
为了避免这种情况就需要命名空间。
var MyNameSpace ={
findProduct;function(){
}
}
var resetProduct = $('reset-product');
var findProduct = $('find-product');
命名空间还可以进一步分割,现在的网页的JavaScript中不仅有你自己的代码,还可能有库代码,广告代码等。为了避免冲突,可以定义一个用来包含自己所有代码的全局对象:
var GiantCorp = {}
然后把自己的全局变量,方法 分门别类的放入GiantCorp中。
2.2用作特定网页专用代码的包装器的单体
在项目中有些JavaScript是所有网页都用的到的,但是有些JavaScript是某个网页专用的,不会被用的别的地方。最好把这两种代码分别包装在自己的单体对象中。
NameSpace.PageName = {
CONSTANT_1:true,
method1:function(){},
init:function(){
}
}
window.onload = function(){
NameSpace.PageName.init();
}
3拥有私有变量的单体
3.1使用下划线
GiantCorp = {
//私有
_stripWhitespace:function(){},
//公共
stringToArray:function(){}
}
你可以通过下划线告诉别人这是私有成员,不要修改它,,但是别人还是可以修改,,,人家不接受你的建议啊。。。
3.2使用闭包
MyNameSpace.Singletion = (function(){
var privateA = 1;
var privateMethod = function(){};
return {
publicA:true,
publicMethod:function(){}
}
})()
4惰性实例化
前面的单体都已一个共同点,他们都是在脚本加载时被创建出来的,对于资源密集或配置开销较大的单体,也许更合适的方法是在使用的时候实例化。
这种惰性单体的特别之处在于,对于他的访问必须借助一个静态方法:
Singleton.getInstance().methodName(),getInstance会检查该单体是否已经被实例化,如果么有那么将它实例化返回,如果已经实例化直接返回现有实例。
MyNameSpace.Signleton = (function(){
var privateAttribute1 = false;
var privateAttribute2 = [1,2,3];
function privateMethod1(){}
function privateMethod2(){}
return {
publicAttribute1:true,
publicAttribute2:10,
publicMethod:function(){
}
}
})()
上面是一个正常的单体,下面我们把它改为惰性的:
MyNameSpace.Signleton = (function() {
var uniqueInstance;
function constructor() {
var privateAttribute1 = false;
var privateAttribute2 = [1, 2, 3];
function publicMethod1() {};
function publicMethod2() {};
return {
publicAttribute1: true,
publicAttribute2: 10,
publicMethod1: function() {},
publicMethod2: function() {},
}
}
return {
getInstance: function() {
if (!uniqueInstance) {
uniqueInstance = constructor();
}
return uniqueInstance;
}
}
})();
console.log(MyNameSpace.Signleton.getInstance().publicAttribute1);