javascript是一门无类语言,也正是因为如此,生搬硬套单例模式的概念毫无意义。在Javascript中创建对象的方法非常简单,既然我们只需要一个唯一的“对象”,为什么要为它先创建一个“类呢”?
单例模式的核心是:确保只有一个实例,并且提供全局访问
全局模式不是单例模式,但在Javascript开发中,我们经常会把全局变量当作单例来使用。例如:
var a={};
当用这种方式创建对象a的时候,对象a确实是独一无二的。如果变量a被声明在全局作用域中,则我们可以在代码中的任意位置使用这个变量,全局变量提供给全局访问是理所应当的。这样就满足了单例模式的两个条件。
但是全局变量存在很多问题,它很容易造成命名空间的污染。在大中型项目中,如果不加以限制和管理,程序中可能存在很多这样的变量。Javascript中的变量也很容易被不小心覆盖,相信每个Javascript开发者都曾经经历过变量冲突的痛苦,就向上面的变量a,随时都可能被别人覆盖
如何减少全局变量的命名污染?
使用命名空间
最简单的方式就是用对象字面量的方式:
var namespace={
a:function(){
alert(1)
},
b:function(){
alert(2)
}
}
这样把a,b限制在命名空间namespace中,通过访问命名空间来获取单例a,既可以全局访问,并且全局只有一个,还可以减少全局变量的次数,减少全局变量的命名污染
使用闭包创建私有变量
这种方法把一些变量封装在闭包内部,只是暴露一些接口与外界通信
var user=(funtion(){
var _name='sven',
_age=29;
return {
getUserInfo: function(){
return _name+'-'+_age
}
}
})();
我们用下划线来约定私有变量_name和_age,他们被封装在闭包产生的作用域中,外部是访问不到这两个变量的,这就避免了对全局的命令污染。
惰性单例
惰性单例指的是在我们需要的时候才创建对象实例。惰性单例是单例模式中的重点,
如下所示:
var getSingle=function(fn){
var result;
return function(){
return result||(result = fn.apply(this,arguments))
}
}
在我们使用的时候先传入一个需要执行的函数,result变量因为身在闭包中,它永远不会被销毁,在将来的请求中,如果result已经被赋值,那么就直接返回这个值,如果不存在就调用传入进来的fn函数方法。
这样不管你调用几次方法,只要result只会被执行一次。