简单点来讲,单例模式就是确保某个类只有一个实例,而且最好只被建立过一次。对计算机来讲,像打印机,线程池都是经典的单例模式。对于JavaScript所处的前端环境来讲,像登陆悬浮框,在整个页面中只会有一个,不管用户点击多少次,只会被建立一次。前端
单例模式很是好理解,无非是办公室有个打印机,你们一块儿公用,不必再每一个人单独买一个了。因此按照这样的理解,先写出前端建立悬浮登陆框的前端代码:设计模式
var createLoginDialog = function(){ var div = document.createElement('div'); div.innerHTML='登陆悬浮框'; var closeBtn = document.createElement('button'); closeBtn.innerHTML = 'X'; div.appendChild(closeBtn); closeBtn.onclick = function(){ div.style.display='none'; } document.body.appendChild(div); return div; } document.getElementById('loginBtn').onclick = function(){ var loginDiv = createLoginDialog(); }
这应该是咱们平时写出的“通常”实现单例代码,看起来单例是实现了。但有很大问题,就是每次建立都会新生成一个div,性能损耗不谈,自己也不是真正实现了单例模式。
单例模式的关键实现一是要在须要建立的时候才开始建立,即惰性建立,第二就是只被建立一次,再次使用的时候,不须要重复建立。在其余语言实现中,须要借助静态方法或者其余手段来使代码驻留内存,达到这一目的。JavaScript却不提供,但内存驻留却使咱们想到了闭包。
因此再次修改代码,建立一个闭包来实现。闭包
var createLoginDialog = (function(){ var div; return function(){ if(!div){ div = document.createElement('div'); div.innerHTML='登陆悬浮框'; var closeBtn = document.createElement('button'); closeBtn.innerHTML = 'X'; div.appendChild(closeBtn); closeBtn.onclick = function(){ div.style.display='none'; } document.body.appendChild(div); }else{ div.style.display='block'; } return div; } })(); document.getElementById('loginBtn').onclick = function(){ var loginDiv = createLoginDialog(); }
实际上,对于js单例模式最核心的逻辑就是app
var obj; if(!obj){ obj = XXX; }
而对于以上最后写出的建立代码,也不尽完美,由于它违反了设计模式中的单一职原则。即建立对象和管理单例的逻辑都放在一个类的内部。
据此,咱们能够剥离出建立单例模式的方法性能
var getSingleton = function(fn){ var result; return function(){ return result || (result = fn.apply(this,arguments)); } }
最终在这个方法下实现代码:this
var createLoginDialog = function(){ var div = document.createElement('div'); div.innerHTML='登陆悬浮框'; var closeBtn = document.createElement('button'); closeBtn.innerHTML = 'X'; div.appendChild(closeBtn); closeBtn.onclick = function(){ div.style.display='none'; } document.body.appendChild(div); return div; } var getSingleton = function(fn){ var result; return function(){ return result || (result = fn.apply(this,arguments)); } } var createSingletonLogin = getSingleton(createLoginDialog); document.getElementById('loginBtn').onclick = function(){ var loginDiv = createSingletonLogin(); loginDiv.style.display = 'block'; }