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只会被执行一次。