成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

JavaScript單例模式的介紹和使用

本篇文章將介紹JavaScript設(shè)計模式中的單例模式。有一定的參考價值,閱讀完整文相信大家對JavaScript設(shè)計模式中的單例模式有了一定的認(rèn)識。

目前創(chuàng)新互聯(lián)公司已為近1000家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站托管、服務(wù)器托管、企業(yè)網(wǎng)站設(shè)計、余干網(wǎng)站維護等服務(wù),公司將堅持客戶導(dǎo)向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

  • 概念

顧名思義,只有一個實例

定義:保證一個類僅有一個實例,并提供一個訪問它的全局訪問點

看到這樣的定義,你的腦海中是否會冒出 全局變量 的概念呢。不可否認(rèn),全局變量是符合單例模式的概念的。但是,我們通常不會也不應(yīng)該將它作為一個單例來使用,原因有以下兩點:

  • 全局命名污染

  • 不易維護,容易被重寫覆蓋

在 ES6 之前,我們通常會使用一個構(gòu)造函數(shù)來模擬一個類,現(xiàn)在我們也可以直接使用 class 關(guān)鍵字來創(chuàng)建一個類,雖然其本質(zhì)也是原型

想要保證一個類僅有一個實例,我們需要提供一個變量來標(biāo)志當(dāng)前是否已經(jīng)為一個類創(chuàng)建過實例。所以,單例模式的核心就是:確保只有一個實例,并提供全局訪問

圍繞這個核心,我們也就基本清楚了單例模式的實現(xiàn)方式

實現(xiàn)


基礎(chǔ)版

根據(jù)單例模式的定義,我們可以用以下方式簡單實現(xiàn)

var Singleton = function(name){    
  this.name = name
}

Singleton.instance = null // 初始化一個變量Singleton.getInstance = function(name) {// 判斷這個變量是否已經(jīng)被賦值,如果沒有就使之為構(gòu)造函數(shù)的實例化對象// 如果已經(jīng)被賦值了就直接返回
  if(!this.instance) {   
   this.instance = new Singleton(name)
   }    
  return this.instance
}
var a = Singleton.getInstance('Tadpole')
var b = Singleton.getInstance('Amy')
a === b // true

以上代碼,清晰的反映出了單例模式的定義。通過一個中間變量的方式,只初始化一個實例,所以最終 a 和 b 是完全相等的

我們也可以用 ES6 的 class 關(guān)鍵字來實現(xiàn)

class Singleton {    
    constructor(name){   
        this.name = name     
      this.instance = null
  }    
  // 提供一個接口對類進行實例化
    static getInstance(name) { 
        if(!this.instance) { 
          this.instance = new Singleton(name)
      }       
      return this.instance
   }
}

不難發(fā)現(xiàn),ES6 的實現(xiàn)方式和我們通過構(gòu)造函數(shù)的方式實現(xiàn)基本是一致的

存在問題:

  • 不夠 透明,我們需要約束類實例化的調(diào)用方式

  • 耦合度過高,功能業(yè)務(wù)代碼耦合在一起不利于后期維護

構(gòu)造函數(shù)

讓我們對上面的方式做一個簡單的修改

// 將變量直接掛在構(gòu)造函數(shù)上面,最終將其返回
  function Singleton(name) {   
     if(typeof Singleton.instance === 'object'){ 
        return Singleton.instance
     }  
     this.name = name
      return Singleton.instance = this
 }  
 // 正常創(chuàng)建實例
 
 var a = new Singleton('Tadpole')
 var b = new Singleton('Amy')

解決了基礎(chǔ)版類不夠 透明 的問題,可以使用 new 關(guān)鍵字來初始化實例,但同時也存在著新的問題

  • 判斷 Single.instance 類型來返回,可能得不到預(yù)期結(jié)果

  • 耦合度過高

這種方式也可以通過 ES6 方式來實現(xiàn)

// 將 constructor 改寫為單例模式的構(gòu)造器
class Singleton {    
constructor(name) {    
    this.name = name 
    if(!Singleton.instance) {
       Singleton.instance = this
    }       
    return Singleton.instance
  }
}

閉包

通過單例模式的定義,想要保證只有一個實例并且可以提供全局訪問。那么,閉包肯定也是可以實現(xiàn)這樣的需求

var Singleton = (function () {  
var SingleClass = function () {}; 
var instance; 
return function () {      
 if (!instance) { 
    instance = new SingleClass() // 如果不存在 則new一個
 }        
 return instance;
}
})()

通過閉包的特性,保存一個變量并最終將其返回,提供全局訪問

同樣的,以上的代碼還是沒有解決耦合度的問題

讓我們仔細觀察這一段代碼,如果我們將其中構(gòu)造函數(shù)的部分提取到外部,是否就實現(xiàn)了功能的分離呢

代理實現(xiàn)

修改一下上面的代碼

function Singleton(name) {   
 this.name = name
}
var proxySingle = (function(){  
  var instance 
  return function(name) {  
    if(!instance) {
      instance = new Singleton(name)
    }  
  return instance
 }
})()

將創(chuàng)建函數(shù)的步驟從函數(shù)中提取出來,把負(fù)責(zé)管理單例的邏輯移到了代理類 proxySingle 中。這樣做的目的就是將 Singleton 這個類變成一個普通的類,我們就可以在其中單獨編寫一些業(yè)務(wù)邏輯,達到了邏輯分離的效果

我們現(xiàn)在已經(jīng)達到了邏輯分離的效果,并且也不 透明 了。但是,這個負(fù)責(zé)代理的類是否已經(jīng)完全符合我們的要求呢,答案是否定的。設(shè)想一下,如果我們的構(gòu)造函數(shù)有多個參數(shù),我們是不是也應(yīng)該在代理類中體現(xiàn)出來呢

那么,有沒有更通用一些的實現(xiàn)方式呢

通用惰性單例

在前面的幾個回合,我們已經(jīng)基本完成了單例模式的創(chuàng)建?,F(xiàn)在,我們需要尋求一種更通用的方式解決之前留下來的問題

試想一下,如果我們將函數(shù)作為一個參數(shù)呢

// 將函數(shù)作為一個參數(shù)傳遞
var Singleton = function(fn) { 
   var instance
   return function() {        // 通過apply的方式收集參數(shù)并執(zhí)行傳入的參數(shù)將結(jié)果返回
     return instance || (instance = fn.apply(this, arguments))
   }
}

這種方式最大的優(yōu)點就是相當(dāng)于緩存了我們想要的結(jié)果,并且在我們需要的時候才去調(diào)用它,符合封裝的單一職責(zé)

應(yīng)用

前面有說過,所有的模式都是從實踐中總結(jié)而來,下面就讓我們來看看它在實際開發(fā)中都有哪些應(yīng)用吧

通過單例模式的定義我們不難想出它在實際開發(fā)中的用途,比如:全局遮罩層

一個全局的遮罩層我們不可能每一次調(diào)用的時候都去創(chuàng)建它,最好的方式就是讓它只創(chuàng)建一次,之后用一個變量將它保存起來,再次調(diào)用的時候直接返回結(jié)果即可

單例模式就很符合我們這樣的需求

// 模擬一個遮罩層var createDiv = function () {    
        var div = document.createElement('div')
    div.style.width = '100vw'
    div.style.height = '100vh'
    div.style.backgroundColor = 'red'
    document.body.appendChild(div)  
    return div
}// 創(chuàng)建出這個元素var createSingleLayer = Singleton(createDiv)document.getElementById('btn').onclick = function () {    // 只有在調(diào)用的時候才展示
    var divLayer = createSingleLayer()
}

當(dāng)然,在實際應(yīng)用中還是有很多適用場景的,比如登錄框,還有我們可能會使用到的 Vux 之類的狀態(tài)管理工具,它們實際上都是契合單例模式的

后記

單例模式是一種簡單而又實用的模式,通過創(chuàng)建對象和管理單例的兩個方法,我們就可以創(chuàng)造出很多實用且優(yōu)雅的應(yīng)用。當(dāng)然,它也有自身的缺點,比如只有一個實例。

看完上述內(nèi)容,你們對JavaScript單例模式有進一步的了解嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀。

當(dāng)前名稱:JavaScript單例模式的介紹和使用
網(wǎng)頁路徑:http://jinyejixie.com/article48/pgehep.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、、用戶體驗面包屑導(dǎo)航、建站公司、虛擬主機

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化
巴里| 巴彦县| 全州县| 夏津县| 张家港市| 兴海县| 军事| 关岭| 资中县| 北流市| 阿拉善左旗| 怀来县| 阳春市| 大庆市| 哈密市| 林口县| 新郑市| 兴仁县| 齐河县| 岚皋县| 蓬莱市| 余庆县| 马边| 侯马市| 吴江市| 开平市| 织金县| 阿拉善左旗| 张掖市| 柞水县| 长武县| 历史| 包头市| 天台县| 武强县| 满洲里市| 泗洪县| 迁安市| 陕西省| 美姑县| 上林县|