首頁 > 軟體

JavaScript單例模式能不能去範例只留單原理解析

2022-12-23 14:00:57

一、單例模式的分類

一個環境中有且只有一個範例,並且當前環境可以存取到它。往小了說,當前環境可以是一個函數作用域、塊級作用域,往大了說可以是全域性window或者global環境。如果按照範例的建立時機進行單例模式的分類,有:

  • 普通單例模式:在環境初始時就建立
  • 惰性單例模式:在某個特定的時機才建立

二、惰性單例模式

從單例模式的定義出發,一個環境中有且只有一個範例,並且使用時才去建立它,那麼就可以把當前單例模式稱之為惰性單例模式

  • 惰性,指的是隻有在使用的時候才去建立
  • 單例,指的是當前環境有且只有單一的一個範例

彈窗案例:在頁面開啟的時候,頁面中有登入按鈕,在點選時,需要建立一個dom節點。
(1)首先,實現一個功能函數:建立節點的函數

var domFun = function () {
    var dom = document.createElement('div');
    dom.innerHTML = '登入視窗demo'
    dom.style.display = 'none';
    document.body.appendChild(dom);
    return dom;
}

(2)其次,建立管理單例的函數

var createSingle = function (fn) {
    var result;
    return function () {
        return result || (result = fn.apply(this, arguments));
    }
}

採用閉包的形式,讓result變數在當前環境不銷燬,如果該變數已經存在,直接返回,如果沒有,讓當前環境呼叫fn功能函數,並賦值給result。該過程保證了當前環境只有一個範例。
(3)將建立節點的函數和管理單例的函數糅合

var createSingleDom = createSingle(domFun)

(4)最後,在點選按鈕的時候,進行範例的建立

var loginBtn = document.querySelector('.login')
loginBtn.onclick = function () {
    var loginDom = createSingleDom()
    console.log(loginDom)
    loginDom.style.display = 'block'
}

該過程實現了只有在點選登入按鈕的時候才建立節點,是惰性的。

整個過程,將建立惰性範例的過程進行了分解,更易於修改和維護,如果,建立的不是div節點,而是,image圖片、iframe巢狀網頁、倒計時等其他內容,只需要替換步驟(1)中的內容即可。

這裡的例子,我們嚴格的強調一個範例的事兒。

二、普通單例模式

在vue中的應用:我們知道vue是一個漸進式框架,主要實現檢視的渲染,其他的功能可以可以通過第三方外掛按需引入,比如路由外掛vue-router和全域性狀態管理vuex

  • 路由vue-router的使用
import Vue from "vue";
import VueRouter from "vue-router";
Vue.use(VueRouter);
  • 狀態vuex的使用
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);

vue通過Vue.use(Vuex)的方式進行vue-routervuex的安裝,Vue.use的程式碼如下:

Vue.use = function (plugin: Function | Object) {
    const installedPlugins = (this._installedPlugins || (this._installedPlugins = []))
    if (installedPlugins.indexOf(plugin) > -1) {
      return this
    }
    // 去掉參數列中的第一個
    const args = toArray(arguments, 1)
    // 將Vue作為this推入到引數的首位
    args.unshift(this)
    if (typeof plugin.install === 'function') {
      plugin.install.apply(plugin, args)
    } else if (typeof plugin === 'function') {
      plugin.apply(null, args)
    }
    installedPlugins.push(plugin)
    return this
}

可以看出,首次執行vue.use(xxx)的時候,會將該外掛推入到陣列installedPlugins中去,再次執行vue.use(xxx)的時候,installedPlugins.indexOf(plugin) > -1true,則終止後續邏輯的執行。也就說,vue.use(xxx)只會讓該外掛執行一次install的安裝。

再看 const installedPlugins = (this._installedPlugins || (this._installedPlugins = [])),是不是發現,這裡也是單例模式的影子,當this._installedPlugins不存在時為其賦值為[],當前存在時直接返回。

單例模式,去掉具體的例,就剩單模式。就像當前例子中,install只執行一次,this._installedPlugins只初始化一次一樣,就體現了一個單字。那這算不算單(例)模式呢?

總結

單例模式是不是可以去範例,只留單呢?這樣,很多隻執行一次的邏輯也就和單例模式能搭上關係了。仁者見仁智者見智,能不能去,純屬個人想法。因為,優秀的單例模式,是經過無數的程式案例得出的經驗性彙總。

以上就是JavaScript單例模式能不能去範例只留單原理解析的詳細內容,更多關於JavaScript單例模式去範例的資料請關注it145.com其它相關文章!


IT145.com E-mail:sddin#qq.com