核心:保证一个类仅有一个实例,并提供一个访问它的全局访问点
js中的单列模式关键字:创建唯一的对象
(一)基本实现:判断是否已有实例,有则直接返回,否则生成实例
var Single = function){
var instance
return function){
ifinstance)return instance
return instance = this
}
}))
var a = new Single)
var b = new Single)
console.loga === b)
这里通过闭包,将单列对象存储在变量instance中
(二)场景:实现一个提示文本的弹出,2秒自动消失,期间再次调用错误提示时不能重复弹出
//实现提示文本
function tipmsg){
var instance = $'<div>'+msg+'</div>')
$'body').appendinstance)
setTimeoutfunction){
instance.remove)
instance = null
},2000)
return instance
}
目前这种实现是有问题的,多次调用时候会有重复div生成,我们可以根据单例模式的基本实现处理下:
//实现单例
var tip_1 = function){
var instance
return functionmsg){
ifinstance)return
instance = $'<div>'+msg+'</div>')
$'body').appendinstance)
setTimeoutfunction){
instance.remove)
instance = null
},2000)
}
}))
(三)通用的单例
--------通用的单例实现代码-----------
function getSinglefn){
let instance
return function){
return instance || instance = fn.applythis,arguments))
}
}
具体应用一:
function createLoginLayer){
var div = document.createElement'div')
div.innerHTML = 'I am login layer'
div.style.display = 'none'
document.body.appendChilddiv)
return div
}
var singleCreateLoginLayer = getSinglecreateLoginLayer)
window.onclick = function){
var loginLayer = singleCreateLoginLayer)
loginLayer.style.display = 'block'
}
通过通用的单例,我们可以将单例的实现和具体业务分离开来,注意:在业务函数中一定要return返回一个具体实例,否则getSingle无效
(四)单例的扩展
有些特殊的场景,我们需要对通用的单例模式进行扩展:
扩展场景一:
//按钮重复提交问题:
$document).on'click',function){
$.ajax{
url:'http://www.baidu.com',
success:function){
console.log'success')
}
})
})
//优化
var goAjax = function){
return $.ajax{
url:'http://www.baidu.com',
success:function){
console.log'success')
},
error:function){
console.log'error')
},
})
}
$document).on'click',getSinglegoAjax))
这个优化目前存着问题,click事件只能执行一次ajax,因为第一次ajax的实例存在了就不会再去执行,所以我们这里需要能够控制到实例
function Single){
this.instance = null
}
Single.prototype.getInstance = functionfn){
let _this = this
return function){
return _this.instance || _this.instance = fn.applythis,arguments))
}
}
var goAjaxSingle = new Single)
var goAjax = function){
return $.ajax{
url:'http://www.baidu.com',
success:function){
console.log'success')
goAjaxSingle.instance = null
}
})
}
$document).on'click',goAjaxSingle.getInstancegoAjax))
这样,在success之前,因为实例存在,所以不能被执行多次ajax
扩展场景二:
//缓存代理场景
function addnum1,num2){
return num1 + num2
}
var proxyFun = functionfn){
let cache = {}
return function){
let args = [].join.callarguments,',')
ifargs in cache){
return cache[args]
}
return cache[args] = fn.applythis,arguments)
}
}
var proxyAdd = proxyFunadd)
proxyAdd1,1)
这里可以看作代理模式,也可以看作单例模式的扩展
