定义
故名思义,保证只有一个实例,并提供全局访问。
伪代码
var obj;
if(!obj) {
obj = new xxx;
}
案例说明:一个登录弹窗
- 页面加载成功后创建登录layer,刚开始是隐藏的,用户点击后显示
let loginLayer = function(){
let div = document.createElement('div');
div.innerHtml = 'login';
div.style.display = 'none';
document.boy.appendChild(div);
return div;
}();
document.getElementById('login').onclick = function() {
div.syle.diisplay = 'block';
}
假如用户不登录则浪费了创建的dom节点 2. 改点点击时创建
function createLoginLayer(){
let div = document.createElement('div');
div.innerHtml = 'login';
div.style.display = 'none';
document.boy.appendChild(div);
return div;
};
document.getElementById('login').onclick = function() {
let div = createLoginLayer();
div.syle.display = 'block';
}
这个实现了惰性创建问题,但每次用户点击都会重新创建loginLayer,失去了单例的意思
3.引出单例
let createLoginLayer = (function (){
let div;
return function(){
// 单例
if(!div) {
div = document.createElement('div');
div.innerHtml = 'login';
div.style.display = 'none';
document.boy.appendChild(div);
}
return div;
}
})();
document.getElementById('login').onclick = function() {
let div = createLoginLayer();
div.syle.display = 'block';
}
现在无论点击关闭多少次,只创建一个login节 4、上面的单例,缺少利用性。违反了单一职责原则,我们需要把不变的部分隔壁出来
// 单例
let getSingle = function(fn){
let res;
return res || (res = fn.apply(this. arguments));
}
// 业务逻辑
let createLoginLayer = function (){
div = document.createElement('div');
div.innerHtml = 'login';
div.style.display = 'none';
document.boy.appendChild(div);
return div;
}
let createLoginLayerSingle = getSingle(createLoginLayer);
document.getElementById('login').onclick = function() {
let div = createLoginLayerSingle();
div.syle.display = 'block';
}
结论
单例 用到了闭包、高阶函数的概念。根本单一职责的原则,把创建对象和单例逻辑分开实现。