JavaScript實(shí)現(xiàn)單例模式實(shí)例分享
傳統(tǒng)單例模式
保證一個(gè)類(lèi)僅有一個(gè)實(shí)例,并提供一個(gè)訪問(wèn)它的全局訪問(wèn)點(diǎn)。
實(shí)現(xiàn)單例核心思想
無(wú)非是用一個(gè)變量來(lái)標(biāo)志當(dāng)前是否已經(jīng)為某個(gè)類(lèi)創(chuàng)建過(guò)對(duì)象,如果是,則在下一次獲取該類(lèi)的實(shí)例時(shí),直接返回之前創(chuàng)建的對(duì)象,接下來(lái)我們用JavaScript來(lái)強(qiáng)行實(shí)現(xiàn)這個(gè)思路,請(qǐng)看代碼:
var Singleton = function( name ){ this.name = name; }; Singleton.prototype.getName = function(){ alert ( this.name ); }; Singleton.getInstance = (function(){ var instance = null; return function( name ){ if ( !instance ){ instance = new Singleton( name ); } return instance; } })();
我們通過(guò)Singleton.getInstance來(lái)獲取Singleton類(lèi)的唯一對(duì)象,這樣確實(shí)是沒(méi)問(wèn)題的,但是js本身是沒(méi)有類(lèi)這種概念的,所以我們強(qiáng)行用傳統(tǒng)單例思想來(lái)實(shí)現(xiàn)是沒(méi)有任何意義的,這樣的代碼又臭又長(zhǎng)(其實(shí)是我自己看著不舒服嘻嘻嘻)。下面我們使用JavaScript的閉包來(lái)實(shí)現(xiàn)一個(gè)單例,請(qǐng)看代碼:
var CreateDiv = (function(){ var instance; var CreateDiv = function( html ){ if ( instance ){ return instance; } this.html = html; this.init(); return instance = this; }; CreateDiv.prototype.init = function(){ var div = document.createElement( 'div' ); div.innerHTML = this.html; document.body.appendChild( div ); }; return CreateDiv; })(); var a = new CreateDiv( 'sven1' ); var b = new CreateDiv( 'sven2' ); alert ( a === b ); // true
可以看到,這樣我們確實(shí)用閉包來(lái)實(shí)現(xiàn)了一個(gè)單例,但這個(gè)代碼還是高度耦合的,CreateDiv的構(gòu)造函數(shù)實(shí)際上負(fù)責(zé)了兩件事情。第一是創(chuàng)建對(duì)象和執(zhí)行初始化init方法,第二是保證只有一個(gè)對(duì)象。這樣的代碼是職責(zé)不明確的,現(xiàn)在我們要把這兩個(gè)工作分開(kāi),構(gòu)造函數(shù)就負(fù)責(zé)構(gòu)建對(duì)象,至于判斷是返回現(xiàn)有對(duì)象還是構(gòu)造新的對(duì)象并返回,我們交給另外一個(gè)函數(shù)去完成,其實(shí)也就是為了滿足一個(gè)編程思想:?jiǎn)我宦氊?zé)原則。這樣的代碼才能更好的解耦,請(qǐng)看下面代碼:
var CreateDiv = function (html) { this.html = html; this.init(); }; CreateDiv.prototype.init = function () { var div = document.createElement('div'); div.innerHTML = this.html; document.body.appendChild(div); }; var ProxySingletonCreateDiv = (function () { var instance; return function (html) { if (!instance) { instance = new CreateDiv(html); } return instance; } })(); var a = new ProxySingletonCreateDiv('sven1'); var b = new ProxySingletonCreateDiv('sven2'); alert(a === b); //true
可以看到,現(xiàn)在我們的構(gòu)造函數(shù)CreateDiv現(xiàn)在只負(fù)責(zé)構(gòu)造對(duì)象,至于是返回現(xiàn)有對(duì)象還是構(gòu)造新的對(duì)象并返回,這件事我們交給了代理類(lèi)proxySingletonCreateDiv來(lái)處理,這樣的代碼看著才舒(zhuang)服(bi)嘛!
最后貼一個(gè)高度抽象的單例模式代碼,惰性單例的精髓!
//單例模式抽象,分離創(chuàng)建對(duì)象的函數(shù)和判斷對(duì)象是否已經(jīng)創(chuàng)建 var getSingle = function (fn) { var result; return function () { return result || ( result = fn.apply(this, arguments) ); } };
形參fn是我們的構(gòu)造函數(shù),我們只要傳入任何自己需要的構(gòu)造函數(shù),就能生成一個(gè)新的惰性單例。比如說(shuō)傳入創(chuàng)建一個(gè)女朋友的構(gòu)造函數(shù),并且調(diào)用getSingle(),就能生成一個(gè)新的女朋友。如果以后再調(diào)getSingle(),也只會(huì)返回剛才創(chuàng)建的那個(gè)女朋友。至于新女朋友——不存在的。
單例常用場(chǎng)景
只需要生成一個(gè)唯一對(duì)象的時(shí)候,比如說(shuō)頁(yè)面登錄框,只可能有一個(gè)登錄框,那么你就可以用單例的思想去實(shí)現(xiàn)他,當(dāng)然你不用單例的思想實(shí)現(xiàn)也行,那帶來(lái)的結(jié)果可能就是你每次要顯示登陸框的時(shí)候都要重新生成一個(gè)登陸框并顯示(耗費(fèi)性能),或者是不小心顯示出了兩個(gè)登錄框。
以上就是我們給大家分享的關(guān)于JS實(shí)現(xiàn)單例模式的相關(guān)學(xué)習(xí)的心得,感謝大家對(duì)腳本之家的支持。
- JavaScript設(shè)計(jì)模式---單例模式詳解【四種基本形式】
- JS 設(shè)計(jì)模式之:?jiǎn)卫J蕉x與實(shí)現(xiàn)方法淺析
- javascript設(shè)計(jì)模式 – 單例模式原理與應(yīng)用實(shí)例分析
- 原生javascript單例模式的應(yīng)用實(shí)例分析
- 基于JavaScript實(shí)現(xiàn)單例模式
- js設(shè)計(jì)模式之單例模式原理與用法詳解
- JavaScript設(shè)計(jì)模式之單例模式原理與用法實(shí)例分析
- JavaScript設(shè)計(jì)模式之單例模式簡(jiǎn)單實(shí)例教程
- NodeJS設(shè)計(jì)模式總結(jié)【單例模式,適配器模式,裝飾模式,觀察者模式】
- JavaScript設(shè)計(jì)模式之單例模式詳解
- javascript 單例模式詳解及簡(jiǎn)單實(shí)例
- 解析Javascript單例模式概念與實(shí)例
- 怎樣用Javascript實(shí)現(xiàn)單例模式
相關(guān)文章
uniapp項(xiàng)目打包為桌面應(yīng)用的方法步驟
本文主要介紹了uniapp項(xiàng)目打包為桌面應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-08-08沒(méi)有document.getElementByName方法
document.getElementByName方法沒(méi)有document.getElementsByName得到的是標(biāo)簽的數(shù)組,下面為大家詳細(xì)介紹下具體的使用,感興趣的朋友可以參考下,希望對(duì)大家有所幫助2013-08-08Iframe自適應(yīng)高度絕對(duì)好使的代碼 兼容IE,遨游,火狐
Iframe自適應(yīng)高度絕對(duì)好使的代碼IE,遨游,火狐都兼容,需要的朋友可以參考下。2011-01-01JavaScript數(shù)組對(duì)象實(shí)現(xiàn)增加一個(gè)返回隨機(jī)元素的方法
這篇文章主要介紹了JavaScript數(shù)組對(duì)象實(shí)現(xiàn)增加一個(gè)返回隨機(jī)元素的方法,涉及javascript針對(duì)數(shù)組及隨機(jī)數(shù)的相關(guān)操作技巧,需要的朋友可以參考下2015-07-07效率高的Javscript字符串替換函數(shù)的benchmark
這是經(jīng)常使用的HTML特殊字符替換函數(shù),即將 &、<、>、" 等函數(shù)替換成 &、<、>、"。通常的作法都是連續(xù)使用數(shù)個(gè) replace 函數(shù),而Clear僅使用一個(gè) replace 就完成了替換。2008-08-08微信小程序自定義tabbar custom-tab-bar 6s出不來(lái)解決方案(cover-view不兼容)
這篇文章主要介紹了微信小程序自定義tabbar custom-tab-bar 6s出不來(lái)解決方案,cover-view不兼容問(wèn)題,需要的朋友可以參考下2019-11-11