在我们理解JavaScript中的单例模式之前,有一个问题:
什么是JavaScript的设计模式?
设计模式:就是针对特定问题给出简洁而优化的解决方案。
我们先来看一个例子:
class CreateObj {
constructor(name){
this.name = name;
}
fn(){
console.log(this.name)
}
}
//实例化构造函数产生实例化对象 obj1 和 obj2
const obj1 = new CreateObj('张三');
const obj2 = new CreateObj('李四');
console.log(obj1 , obj2);
console.log(obj1 === obj2);//输出false
由此我们可以得出一个结论:普通的同一个构造函数实例化产生的对象不相等。
单例模式可以帮我们解决这个问题,使得 obj1 === obj2。
单例模式的实现:
//1、构造一个空函数
function CreateObj(){}
//2、创建一个变量保存原始数值,变量值可以为null,undefined,基本数据类型。
let res = null;
//3、创建单例模式的构造函数
function Singleton(){
if(res === null){
//res 存储的是实例化对象的内存地址
res = new CreateObj();
}
//返回存储的实例化对象的内存地址
return res;
}
//4、实例化构造函数产生对象obj1 和 obj2
const obj1 = Singleton();
const obj2 = Singleton();
console.log(obj1===obj2);//输出 true
我们来读一下这段程序的大致执行过程:
第一次执行:res = null—>判断成立—>实例化对象—>const obj1 = new CreateObj();
第二次执行:res = obj1的内存地址—>判断不成立—>返回之前的实例化对象(obj1的内存地址),故obj2存储的就是obj1的内存地址,故结果为true。
一般单例模式要结合闭包使用,使得全局变量不被污染。
代码演示:
//1、定义立即执行函数
// Utills 存储的是立即执行函数的执行结果,即闭包的返回函数的返回值
const Utills = (function(){
//构造一个函数
function Create(){}
//定义一个变量保存原始值
let res = null;
return function(){
if(res == null){
//res存储构造函数实例化对象的内存地址
res = new Create();
}
return res;
}
})()
const aObj = Utills();
const bObj = Utills();
console.log(aObj === bObj);//true
第一次执行时因为第一次执行时res为空,构造函数会实例化对象, res保存的是这个实例化对象的内存地址并返回,aobj存储的是也是这个内存地址,当第二次执行时res已经存储了这个内存地址,所以判断不成立,返回值依然是这个内存地址,所以bobj存储的也是这个内存地址,之后不管Utills被调用多少次,实例化对象存储的都是这个内存地址。
总结:
单例模式的作用: 通过构造函数声明的实例化对象,如果生成的实例化对象的属性、方法都相同,那么生成的就是同一个实例化对象。