最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript設(shè)計模式之單例模式應(yīng)用場景案例詳解

 更新時間:2023年05月29日 11:07:33   作者:一顆冰淇淋  
這篇文章主要為大家介紹了JavaScript中單例模式的應(yīng)用場景案例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

單例模式

如果希望自己的代碼更優(yōu)雅、可維護(hù)性更高以及更簡潔,往往離不開設(shè)計模式這一解決方案。

在JS設(shè)計模式中,最核心的思想:封裝變化(將變與不變分離,確保變化的部分靈活,不變的部分穩(wěn)定)。

那么來說說第一個常見的設(shè)計模式:單例模式

單例模式保證一個類僅有一個實例,并提供一個訪問它的全局訪問方式,為了解決一個全局使用的類頻繁被創(chuàng)建和銷毀、占用內(nèi)存的問題。

ES5中通過閉包

在ES5中,可以使用閉包(函數(shù)內(nèi)部返回函數(shù)被外界變量所引用,導(dǎo)致這個函數(shù)里面的變量無法被釋放,就構(gòu)建成閉包)來保存這個類的實例。

var Singeton = (function(){
    var instance;
    function User(name,age){
        this.name=name;
        this.age=age;
    }
    return function(name,age){
        if(!instance){
            instance = new User(name,age)
        }
        return instance
    }
})()

此時這個實例一旦生成,每次都是返回這個實例,且不會被修改,可以看到下面的代碼,當(dāng)給 User 對象初始賦值 name:alice,age:18 時,以后再賦值便無效了,以及每次返回都是初始的實例對象。

ES6中使用類的靜態(tài)屬性

以上代碼使用ES6語法來實現(xiàn),通過類的靜態(tài)屬性來保存唯一的實例對象。

class Singeton {
    constructor(name,age){
        if(!Singeton.instance){
            this.name = name;
            this.age = age;
            Singeton.instance = this;
        }
       return Singeton.instance;
    }
}

創(chuàng)建方式仍然是一樣的,通過 new 關(guān)鍵字創(chuàng)建類的實例對象。

案例

那這樣一種設(shè)計模式在開發(fā)中實際有什么用途呢?我們試想這樣一個業(yè)務(wù)場景:訪問網(wǎng)站時,很久沒有操作頁面,此時授權(quán)過期,當(dāng)我們點(diǎn)擊頁面上的任何一個地方,都會彈出一個登錄框。

那么這個登錄框,是全局唯一的,不會存在多份,也不會互相沖突,所以不需要每次都創(chuàng)建一份,保留初始那一份就夠了。

提前創(chuàng)建節(jié)點(diǎn)

我們可能會想到首先在頁面中提前創(chuàng)建節(jié)點(diǎn),編寫好頁面樣式,最后通過控制元素的 display 屬性來達(dá)到顯示和隱藏的效果。

<div class="modal">登錄對話框</div>
<button id="open">打開</button>
<button id="close">關(guān)閉</button>
<style>
  .modal {
    display: none;
    /* 其他布局代碼省略 */
  }
</style>
<script>
  document.querySelector("#open").onclick = function(){
     const modal = document.querySelector('.modal')
     modal.style.display = 'block'
  }
</script>

這樣可以完成需求,全局只有一個登錄框,每次都展示同一個。但問題是dom元素從一開始它創(chuàng)建好并添加到body中,無論是否需要用到,如果有些場景不需要登陸,那么這里初始渲染就會浪費(fèi)空間。

單例模式

那如果不需要初始渲染,僅當(dāng)需要時才使用,并且每次都返回同一個實例的單例模式應(yīng)該如何實現(xiàn)呢?

我們可以這樣處理

<!-- 去除class為modal的標(biāo)簽,動態(tài)創(chuàng)建 -->
<script>
const Modal = (function(){
  let instance = null
  return function(){
      if(!instance){
          instance = document.createElement("div")
          instance.innerHTML = "登錄對話框"
          instance.className = "modal"
          instance.style.display = "none"
          document.body.appendChild(instance)
      }
      return instance
  }
})()
document.querySelector("#open").onclick = function(){
      //創(chuàng)建modal,如果放在外面,一開始就會創(chuàng)建元素
      const modal = Modal()    
      //顯示modal
      modal.style.display = "block"
  }
  document.querySelector("#close").onclick = function(){
      const modal = Modal()    
      modal.style.display = "none"
  }
</script>

雖然上面的方式可以達(dá)到效果,但是創(chuàng)建對象和管理單例的邏輯都放在了對象內(nèi)部,是有些混亂的。并且如果下次需要創(chuàng)建頁面中唯一的 iframe,或者 script 標(biāo)簽,就得將以上函數(shù)照抄一遍。

通用單例

首先拆分函數(shù)邏輯,將執(zhí)行創(chuàng)建對象的邏輯拿出來

const createLayer = function(){
  let div = document.createElement("div")
  div.innerHTML = "登錄對話框"
  div.className = "modal"
  div.style.display = "none"
  document.body.appendChild(div);
  return div;
}
const Modal = (function(){
  let instance = null
  return function(){
      if(!instance){
          instance = createLayer()
      }
      return instance
  }
})()

以上修改后代碼邏輯就更為清晰,但此時還不支持通用化的創(chuàng)建別的組件,這時候我們想想如何將創(chuàng)建單例的方法進(jìn)行一些優(yōu)化,是否可以將單例需要執(zhí)行的函數(shù)抽象化。

const createSingle = (function(fn){
    let instance; 
    return function(){
        return instance || ( instance = fn.apply(this, arguments))
    }
})()

這樣改造后,如果存在創(chuàng)建 iframe 的方法,也可以直接使用。

const createIframe = function() {
  const iframe = document.createElement('iframe');
  iframe.style.display = 'none';
  document.body.appendChild(iframe);
  return iframe
}
const singleIframe = createSingle(createIframe)
document.querySelector("#open").onclick = function(){
 const iframe = singleIframe()
 iframe.style.display = 'block'
}

實際應(yīng)用

以上都是咱小打小鬧的試用,那再來看看社區(qū)中一些非常棒的實現(xiàn)吧~ 比如:React 中常用的狀態(tài)管理工具 Redux 就使用到了單例模式,它有這樣一些要求。

  • 單一數(shù)據(jù)源:整個應(yīng)用的 state 只存在于唯一一個 store 中。
  • State 是只讀的:不要直接改變 state 的值,唯一改變 state 的方法就是觸發(fā) action。
  • reducer 是純函數(shù):需要編寫純函數(shù) reducer 來修改 state 的值。

來看看 Redux 的源碼,為了便于閱讀已刪減部分邏輯判斷和注釋,可以看到通過 store 的 getState 方法每次獲取閉包中的 currentState。

單例模式在內(nèi)存中只有一個實例,可以減少內(nèi)存開支,同時還能在系統(tǒng)設(shè)置全局的訪問點(diǎn),優(yōu)化和共享資源。

以上就是單例模式的相關(guān)介紹。更多有關(guān) 前端、設(shè)計模式 的內(nèi)容請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • JavaScript實現(xiàn)一個Promise隊列小工具

    JavaScript實現(xiàn)一個Promise隊列小工具

    這篇文章主要介紹了JavaScript實現(xiàn)一個Promise隊列小工具,文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-08-08
  • 詳解如何使用mock.js實現(xiàn)接口測試的自動化

    詳解如何使用mock.js實現(xiàn)接口測試的自動化

    這篇文章主要為大家介紹了如何使用mock.js實現(xiàn)接口測試的自動化詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • Typescript?封裝?Axios攔截器方法實例

    Typescript?封裝?Axios攔截器方法實例

    這篇文章主要為大家介紹了Typescript?封裝?Axios攔截器方法實例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • JavaScript文檔對象模型DOM

    JavaScript文檔對象模型DOM

    這篇文章主要介紹了JavaScript文檔對象模型DOM,當(dāng)網(wǎng)頁被加載時,瀏覽器會創(chuàng)建頁面的文檔對象模型,通過可編程的對象模型,JavaScript 獲得了足夠的能力來創(chuàng)建動態(tài)的 HTML。下面來看看文章得詳細(xì)內(nèi)容,需要的朋友可以參考一下
    2021-11-11
  • 高級前端必會的package.json字段知識詳解

    高級前端必會的package.json字段知識詳解

    這篇文章主要為大家介紹了高級前端必會的package.json字段知識詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • buildcheck包報錯問題排查解決

    buildcheck包報錯問題排查解決

    這篇文章主要為大家介紹了buildcheck包報錯問題排查解決,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 利用js實現(xiàn)簡單開關(guān)燈代碼

    利用js實現(xiàn)簡單開關(guān)燈代碼

    這篇文章主要分享的是如何利用js實現(xiàn)簡單開關(guān)燈代碼,下面文字圍繞js實現(xiàn)簡單開關(guān)燈的相關(guān)資料展開具體內(nèi)容,需要的朋友可以參考以下,希望對大家又所幫助
    2021-11-11
  • 微信小程序微信支付接入開發(fā)實例詳解

    微信小程序微信支付接入開發(fā)實例詳解

    這篇文章主要介紹了微信小程序微信支付接入開發(fā)實例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • 微信小程序 加載 app-service.js 錯誤解決方法

    微信小程序 加載 app-service.js 錯誤解決方法

    這篇文章主要介紹了微信小程序 加載 app-service.js 錯誤詳解的相關(guān)資料,在開發(fā)微信小程序過程中出現(xiàn)了app-services.js的錯誤,并解決此問題,需要的朋友可以參考下
    2016-10-10
  • Evil.js項目源碼解讀

    Evil.js項目源碼解讀

    這篇文章主要為大家介紹了最近火爆全網(wǎng)的?Evil.js?源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08

最新評論

东方市| 公主岭市| 沙洋县| 印江| 临海市| 肥乡县| 通辽市| 伊春市| 锡林郭勒盟| 宜昌市| 垫江县| 崇阳县| 当雄县| 罗山县| 文山县| 文登市| 承德市| 霸州市| 定安县| 酒泉市| 平遥县| 阜阳市| 汶上县| 神池县| 阳谷县| 出国| 长岛县| 临安市| 宝清县| 霍邱县| 福建省| 上林县| 南开区| 东平县| 达州市| 卓资县| 淮滨县| 罗平县| 耿马| 台北县| 吉安市|