保证一个特定的类只有一个实例(并且永远是同一个)
在JavaScript中,只有对象没有类,要实现单例模式也有多种方法。
最简单的方式:通过字面量来创建对象,因为在JS中对象之间永远不可能相等,除非它们是同一个对象
使用字面量创建的对象总是唯一的。
实现单例模式的的几种途径
- 在代码中提供一个全局变量来存储创建出来的实例。缺点:该全局变量可能会被轻易的修改和覆盖
- 尝试在构造函数的静态成员中缓存实例属性。缺点:函数的静态属性在外部可以直接修改,容易导致实例对象的丢失。
- 将实例对象包装在闭包中,安全性好,无法轻易修改。缺点:有额外的闭包开销。
全局变量方法
1234567891011121314151617181920//提供全局变量,使用全局变量来接收内部创建出来的实例对象(this)var instance;//提供构造函数function Singleton () {//判断是否已经创建存在过if (instance) {//如果创建过直接返回return instance;}//默认把实例对象赋值给this再传给全局变量instanceinstance = this;//设置实例属性方法this.property = '设置属性';this.fun = function() {'设置方法'};}var obj1 = new Singleton();var obj2 = new Singleton();//两个对象存储数据的地址一样,实际就是一个对象console.log(obj1 === obj2); //true
但是上述方法有一个明显的问题,全局变量instance
容易被修改,造成之后创建的实例指向错误的数据。
改进:通过即使调用函数,把instance
封闭在里面。
这样只能修改构造函数名称,但是修改了的话浏览器会报错提示我们Singleton is not a constructor
,可以很快排错。
构造函数静态属性方法
通过把instance
设置为构造函数Singleton
的静态属性,在一定程度上可以防止被修改。但是通过Singleton.instance
还是可以修改到。
惰性函数方法
实现思路:在构造函数内部声明一个私有变量instance
,利用惰性函数执行过一次后自我更新的特性可以直接返回instance
。
问题:由于惰性函数的自我更新,导致构造函数指向新的对象
在构造函数更新过一次后,新的构造函数创建出来的实例的
constructor
属性还是跟第一次创建出来的实例一样,指向更新前的构造函数。并且创建对象以后设置的原型对象和单例对象不是同一个(由于更新之后,新构造函数的原型对象与旧构造函数的原型对象不是同一个),导致创建对象后设置到原型对象的属性和方法无法访问。
改进方法:利用原型链继承,将新构造函数原型对象设置为旧构造函数的实例。同时用新构造函数创建实例赋值给instance
,并修正instance
构造器属性指向。
步骤:
1. 提供一个构造函数
2. 在构造函数内部提供一个私有变量
3. 利用惰性函数实现构造函数的自我更新(直接返回instance)
4. 设置新构造函数的原型对象是旧构造函数的一个实例
5. 使用新构造函数创建对象并赋值给instance
6. 修正构造器属性指向更新后的构造函数
7. 使用instance设置属性和方法
8. 返回instance