經過一個getInstance
方法獲取對象,首先判斷一個對象是否存在,若是存在則就將改對象返回,若是不存在就先實例化對象(建立對象),而後再返回javascript
let Singleton = function(name){ this.name = name; } // 將實例存儲在對象中 Singleton.getInstance = function() { // 若是自己到 if(this.instance === null){ this.instance = new Singleton(); } return this.instance; } let aIns = Singleton.getInstance("test"); let bIns = Singleton.getInstance("test"); console.log(aIns === bIns);
// 將實例使用閉包的形式存儲起來 Singleton.getInstanceNew = (function() { let instance = null; return function(){ if(instance === null){ instance = new Singleton(); } return instance; } }()) let cIns = Singleton.getInstanceNew("test"); let dIns = Singleton.getInstanceNew("test"); console.log(cIns === dIns, aIns === dIns);
咱們看到以上兩個方法,都是建立單例的簡單方法,雖然實現了,可是若是別人不知道這個對象時單例的,仍是可使用
new
關鍵字建立。而且再也不是單例了,因此很容易違背了咱們單例的初心html
咱們依然經過new
建立實例,可是建立的仍是單例的,這樣即便不須要咱們特地去囑咐這個對象是單例前端
var TransparentSingleton = (function() { var instance = null; var TransparentSingleton = function(){ if(instance){ return instance; } this.init(); return instance = this; } TransparentSingleton.prototype.init = function(){ console.log("Dom操做") } return TransparentSingleton; }()) let eIns = new TransparentSingleton(); let fIns = new TransparentSingleton(); console.log(eIns === fIns);
這種方法雖然知足了咱們的要求,可是這裏存在一個問題,就是內部的
TransparentSingleton
的這對象,成爲了一個私有對象,咱們在外面沒法訪問到java
var CreateDom = function(html){ this.html = html; this.init(); } CreateDom.prototype.init = function(){ console.log(this.html); } var ProxyCreateDom = (function(){ let instance = null; return function(html){ if(instance === null){ instance = new CreateDom(html); } return instance; } }()) let hIns = new ProxyCreateDom("測試"); let gIns = new ProxyCreateDom("前端"); console.log(hIns === gIns, hIns.html, gIns.html)
這裏咱們將對象提了出來了,經過
ProxyCreateDom
去建立一個關於CreateDom
的單例,可是這個版本是比較有限的,咱們能夠看到這個代理單例並非一個可複用的,代碼極可能會翻倍。而且無論咱們需不要單例,其實ProxyCreateDom
裏的instance
就建立了。而且這個是屬於傳統面嚮對象語言的,在JavaScript這個沒有類的語言中,這樣建立意義並不大閉包
let getSingleton = function(func) { let result = null; return function(){ return result || (result = func.apply(this, arguments)); } } function createLoginLayer(){ var div = document.createElement("div"); div.innerHTML = "我是登陸浮窗"; div.style.display = "none"; document.body.appendChild(div); return div; } /** * 測試代碼 */ let createSingleLoginLayer = getSingleton(createLoginLayer); // 添加一個登錄浮窗 document.getElementById("loginTest").onclick = function(){ var loginLayer = createSingleLoginLayer(); loginLayer.style.display = "block" } // 建立一個iframe的單例 var createSingleIfame = getSingleton(function () { var iframe = document.createElement("iframe"); document.body.appendChild(iframe); return iframe; }) // 建立一個iframe,並將src屬性設置爲百度 document.getElementById("loginBtn").onclick = function(){ var loginLayer = createSingleIfame(); loginLayer.src = "http://baidu,com"; } // 將浮窗單例隱藏 document.getElementById("closeLoginBtn").onclick = function(){ var loginLayer = createSingleLoginLayer(); loginLayer.style.display = "none" } // 改變iframe的src屬性 document.getElementById("changeUrlBtn").onclick = function(){ var loginLayer = createSingleIfame(); loginLayer.src = "http://127.0.0.1:5500/index.html"; }