js 单例

208 阅读1分钟

定义

故名思义,保证只有一个实例,并提供全局访问。

伪代码

var obj;
if(!obj) {
	obj = new xxx;
}

案例说明:一个登录弹窗

  1. 页面加载成功后创建登录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';
}

结论

单例 用到了闭包、高阶函数的概念。根本单一职责的原则,把创建对象和单例逻辑分开实现。