一般来说,单例就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。
单例模式是指在内存中只会创建且仅创建一次对象的设计模式。
在程序中多次使用同一个对象且作用相同时,为了防止频繁的创建对象使得内存飙升,单例模式可以让程序仅在内存中创建一个对象,让所有需要调用的地方都共享这一单例对象。
单例模式可以分为两种类型:
注意:上面两种创建单例对象的方式的构造器都要私有化。
在前端开发中 ,实现单例的方式有很多,最简单的方式就是:使用对象字面量的方式。这样对象里可以包含需要的属性和方法:
let mySingleton = {
property1: "something",
property2: "something else",
method1: function () {
console.log('hello world');
}
};
如果以后要扩展该对象,可以添加私有成员和方法。然后使用闭包在其内部封装这些变量和函数声明,只暴露你想暴露的public成员和方法。
样例代码如下:
let mySingleton = function () {
/* 这里声明私有变量和方法 */
let privateVariable = 'something private';
function showPrivate() {
console.log(privateVariable);
}
/* 公有变量和方法(可以访问私有变量和方法) */
return {
publicMethod: function () {
showPrivate();
},
publicVar: 'the public can see this!'
};
};
let single = mySingleton();
single.publicMethod(); // 输出 'something private'
console.log(single.publicVar); // 输出 'the public can see this!'
上面的代码很不错了,但如果我们想做到只有在使用的时候才初始化,那该如何做呢?
为了节约资源的目的,我们可以另外一个构造函数里来初始化这些代码,如下:
let Singleton = (function () {
let instantiated;
function init() {
/*这里定义单例代码*/
return {
publicMethod: function () {
console.log('hello world');
},
publicProperty: 'test'
};
}
return {
getInstance: function () {
if (!instantiated) {
instantiated = init();
}
return instantiated;
}
};
})();
/*调用公有的方法来获取实例:*/
Singleton.getInstance().publicMethod();
单例一般是用在系统间各种模式的通信协调上,下面的代码是一个单例的最佳实践:
let SingletonTester = (function () {
//参数:传递给单例的一个参数集合
function Singleton(args) {
//设置args变量为接收的参数或者为空(如果没有提供的话)
let args = args || {};
//设置name参数
this.name = 'SingletonTester';
//设置pointX的值
this.pointX = args.pointX || 6; //从接收的参数里获取,或者设置为默认值
//设置pointY的值
this.pointY = args.pointY || 10;
}
//实例容器
let instance;
let _static = {
name: 'SingletonTester',
//获取实例的方法
//返回Singleton的实例
getInstance: function (args) {
if (instance === undefined) {
instance = new Singleton(args);
}
return instance;
}
};
return _static;
})();
let singletonTest = SingletonTester.getInstance({ pointX: 5 });
console.log(singletonTest.pointX); // 输出 5
接着介绍使用惰性单例模式,实现弹框的demo
const createModal = function (message) {
const box = document.createElement('div')
box.innerHTML = message
box.className = 'box'
document.body.appendChild(box)
return box
}
const createAlertMessaeg = CreateSingleV1(createModal)
modalAlert.onclick = function (params) {
const alertMessaeg = createAlertMessaeg('独孤九剑yyds')
}
来具体说一下单例模式的优缺点吧
《前端面试题宝典》经过近一年的迭代,现已推出 小程序
和 电脑版刷题网站 (https://fe.ecool.fun/
),欢迎大家使用~
同时,我们还推出了面试辅导的增值服务,可以为大家提供 “简历指导” 和 “模拟面试” 服务,感兴趣的同学可以联系小助手(微信号:interview-fe)进行报名。