欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

單例模式

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

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

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

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

ES5中通過閉包

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

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
    }
})()

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

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

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

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í)例對象。

案例

那這樣一種設(shè)計模式在開發(fā)中實(shí)際有什么用途呢?我們試想這樣一個業(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)需要時才使用,并且每次都返回同一個實(shí)例的單例模式應(yīng)該如何實(shí)現(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'
}

實(shí)際應(yīng)用

以上都是咱小打小鬧的試用,那再來看看社區(qū)中一些非常棒的實(shí)現(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)存中只有一個實(shí)例,可以減少內(nèi)存開支,同時還能在系統(tǒng)設(shè)置全局的訪問點(diǎn),優(yōu)化和共享資源。

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

相關(guān)文章

  • 微信小程序 視圖層(xx.xml)和邏輯層(xx.js)詳細(xì)介紹

    微信小程序 視圖層(xx.xml)和邏輯層(xx.js)詳細(xì)介紹

    這篇文章主要介紹了微信小程序 視圖層(xx.xml)和邏輯層(xx.js)詳細(xì)介紹的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • 微信小程序 Toast自定義實(shí)例詳解

    微信小程序 Toast自定義實(shí)例詳解

    這篇文章主要介紹了微信小程序 Toast自定義實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-01-01
  • Web?Animations?API實(shí)現(xiàn)一個精確計時的時鐘示例

    Web?Animations?API實(shí)現(xiàn)一個精確計時的時鐘示例

    這篇文章主要為大家介紹了Web?Animations?API實(shí)現(xiàn)一個精確計時的時鐘示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • JavaScript 中的文檔對象模型 DOM

    JavaScript 中的文檔對象模型 DOM

    DOM,即文檔對象模型,前端開發(fā)工程師必學(xué)的基礎(chǔ)知識,在本文將介紹如何在 HTML 文檔中選擇元素、如何創(chuàng)建元素、如何更改內(nèi)聯(lián) CSS 樣式以及如何監(jiān)聽事件,需要的朋友可以參考一下
    2021-10-10
  • Thinkphp5微信小程序獲取用戶信息接口的實(shí)例詳解

    Thinkphp5微信小程序獲取用戶信息接口的實(shí)例詳解

    這篇文章主要介紹了Thinkphp5微信小程序獲取用戶信息接口的實(shí)例詳解的相關(guān)資料,希望通過本文能幫助到大家,需要的朋友可以參考下
    2017-09-09
  • 微信小程序 Storage API實(shí)例詳解

    微信小程序 Storage API實(shí)例詳解

    這篇文章主要介紹了微信小程序 Storage API實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2016-10-10
  • 微信小程序 歡迎頁面的制作(源碼下載)

    微信小程序 歡迎頁面的制作(源碼下載)

    這篇文章主要介紹了微信小程序 歡迎頁面的制作含(源碼下載)的相關(guān)資料,這里實(shí)現(xiàn)歡迎頁面,開始做應(yīng)用的時候都會用到,需要的朋友可以參考下
    2017-01-01
  • Google 地圖獲取API Key詳細(xì)教程

    Google 地圖獲取API Key詳細(xì)教程

    本文主要介紹Google 地圖API Key,開發(fā)Google 地圖應(yīng)用的朋友都知道,在開發(fā)的前需要免費(fèi)的Google 地圖API Key,這里詳細(xì)給出獲得API Key的流程,有需要的小伙伴參考下
    2016-08-08
  • JavaScript事件委托原理

    JavaScript事件委托原理

    這篇文章主要介紹了JavaScript事件委托原理,?事件委托也稱為事件代理。就是利用事件冒泡,把子元素的事件都綁定到父元素上。如果子元素阻止了事件冒泡,那么委托就無法實(shí)現(xiàn),下面我們一起來學(xué)習(xí)文章的具體詳細(xì)內(nèi)容吧
    2021-12-12
  • Promise改寫獲取螢石云直播地址接口示例

    Promise改寫獲取螢石云直播地址接口示例

    這篇文章主要為大家介紹了Promise改寫獲取螢石云直播地址接口示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-08-08

最新評論