持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第15天,点击查看活动详情
什么是单例模式
保证一个类仅有一个实例,并提供一个访问它的全局访问点
比如 redux 中的 store,线程池,全局缓存,浏览器 window 对象等。
实现一个单例模式
实现:通过一个变量来标记是否为某个类创建过对象,如果创建过则在下次创建的时候直接返回之前创建的对象
单例模式的核心是确保只有一个实例,并提供全局访问
class Person {
constructor(name) {
this.name = name;
this.init();
}
init() {
this.age = 18;
}
}
// 代理实现单例模式
const ProxySingletonPerson = (function () {
var instance;
return function (name) {
// 缓存代理
if (!instance) {
instance = new Person(name);
}
return instance;
};
})();
const p1 = new ProxySingletonPerson('xx');
const p2 = new ProxySingletonPerson('cd');
// p1: Person {name: 'xx', age: 18}
// p2: Person {name: 'xx', age: 18}
p1 === p2; // true
可以看到 p1 和 p2 返回的都是第一次 new 的那个实例( p1 ),说明他是惰性的
通用的惰性单例
let getSingle = function (fn) {
let result;
return function () {
if (!result) {
result = fn.apply(this, arguments);
}
return result;
// or
// return result || ( result = fn .apply(this, arguments ) );
};
};
我们在看个例子:
const createLogin = function () {
var div = document.createElement('div');
div.innerHTML = 'this is login';
div.id = 'loginBtn';
document.body.appendChild(div);
return div;
};
const createIframe = function () {
var iframe = document.createElement('iframe');
document.body.appendChild(iframe);
return iframe;
};
// 在页面创建登录按钮
const loginDom = getSingle(createLogin());
// 创建一个 iframe 单例
const iframe = getSingle(createIframe);
// 点击登录按钮,通过 iframe 加载第三方页面
document.getElementById('loginBtn').onclick = function () {
var loginLayer = iframe();
loginLayer.src = 'https://wuxiaobai.cn';
};
总结
在 getSinge 函数中,实际上也提到了闭包和高阶函数的概念。
单例模式是一种简单但非常实用的模式,特别是惰性单例技术,在合适的时候才创建对象,并且只创建唯一的一个,这对于我们队页面的优化也是有一些帮助,比如懒加载。