JavaScript之單例實戰

1、概述

所謂單例模式,顧名思義即一個類只有一個實例。chrome

因此,當咱們建立一個實例時,就必須判斷其是否已經存在了這個實例,若是已經存在了這個實例,那麼就返回這個已經存在的實例,無需再建立一個單例模式嘛,核心就是一個類只有一個 實例;若是不存在,就建立這個實例咯。閉包

好了,單例模式的核心思想以及建立流程大體搞清楚了,那麼咱們就開始看看,在Javascript的世界中,具體該怎麼實現呢?函數

2、實戰一

核心思路:利用Javascript的做用域,造成閉包,從而能夠建立私有變量(假設咱們將這個私有變量取名爲instance),而後將建立的實例賦予這個私有變量instance就ok了。每當想建立這個類的實例時,先判斷instance是否已經引用了存在的實例,若是沒有引用,即這個類沒有被建立實例,so建立一個實例,而後將其賦予給instance;若是instance已經引用,即已存在了該類的實例,so無需再建立,直接使用這個instance就ok了。
this

第一步:執行匿名函數,防止命名空間污染。在匿名函數中,首先定義個上述提到的私有變量instance以及一個類。這個類,我假設它有名字(name)和年齡(age)兩個屬性字段以及一個輸出他們名字的方(displayInfo)哈。spa

'use strict'
var singletonAccepter =(function(){
    //默認將instance賦予null
    var instance = null;
    //類:SupposeClass
    function SupposeClass( args ){
        var args = args || {};
        this.name = args.name || 'Monkey';
        this.age = args.age || 24;
    };
    SupposeClass.prototype = {
        constructor: SupposeClass,
        displayInfo: function(){
            console.log('name: ' + this.name + '   age: ' + this.age);
        }
    };
})();

第二步:利用return + 對象字面量,將咱們想,向外暴露的東東,往外拋。prototype

以下:3d

return {
    //類的名字
    name: 'SupposeClass',
    //建立類的實例方法
    getInstance: function( args ){
        //利用私有變量instance實現單例模式
        if( instance === null ){
            instance = new SupposeClass( args );
        }
        return instance;
    }
};

最後,合併第一步第二步的代碼就造成了一個單例模式啦。指針

以下:日誌

'use strict'
var singletonAccepter =(function(){
    //默認將instance賦予null
    var instance = null;
    //類:SupposeClass
    function SupposeClass( args ){
        var args = args || {};
        this.name = args.name || 'Monkey';
        this.age = args.age || 24;
    };
    SupposeClass.prototype = {
        constructor: SupposeClass,
        displayInfo: function(){
            console.log('name: ' + this.name + '   age: ' + this.age);
        }
    };
    return {
        //類的名字
        name: 'SupposeClass',
        //建立類的實例方法
        getInstance: function( args ){
            //利用私有變量instance實現單例模式
            if( instance === null ){
                instance = new SupposeClass( args );
            }
            return instance;
        }
    };
})();

接下來,咱們檢驗一下寫的這個單例模式。在上述代碼中,在類SupposeClass中加入console.log,若是隻建立了它的一個實例,那麼就只會打印一個日誌哦。
修改代碼以下:code

'use strict'
var singletonAccepter =(function(){
    var instance = null;
    function SupposeClass( args ){
        var args = args || {};
        this.name = args.name || 'Monkey';
        this.age = args.age || 24;
        //檢驗單例模式
        console.log('this is created!');
    };
    SupposeClass.prototype = {
        constructor: SupposeClass,
        displayInfo: function(){
            console.log('name: ' + this.name + '   age: ' + this.age);
        }
    };
    return {
        name: 'SupposeClass',
        getInstance: function( args ){
            if( instance === null ){
                instance = new SupposeClass( args );
            }
            return instance;
        }
    };
})();

調用兩次getInstance方法,看看打印幾條記錄

singletonAccepter.getInstance();
singletonAccepter.getInstance();

執行代碼,打開chrome截圖以下:

鑑定完畢,只被實例一次。

3、實戰二

思路:利用屬性來判斷是否已存在實例。
什麼意思?
在Javascript的世界裏,類(function)不也是對象嘛,so對其賦予一個屬性instance,用來引用建立的實例,經過判斷instance是否已引用建立的實例就OK咯。

以下:

function singletonAccepter( args ){
    //判斷Universe.instance是否已存在實例
    if(typeof singletonAccepter.instance === 'object'){
        return singletonAccepter.instance;
    }
    this.name = args.name || 'Monkey';
    this.age = args.age || 24;
    singletonAccepter.instance = this;
};
singletonAccepter.prototype = {
    constructor: singletonAccepter,
    displayInfo: function(){
        console.log('name: ' + this.name + '   age: ' + this.age);
    }
};
4、實戰三

在Javascript的世界裏,this是引用的對象。
還記得JavaScript是怎麼經過new建立對象的麼?
new:
  一、建立一個新的對象,這個對象的類型時object;
  二、將這個對象的__proto__隱指針指向原型prototype;
  三、執行構造函數,當this被說起的時候,表明新建立的對象;
  四、返回新建立的對象。
  注:假若在最後return了,那麼return的是基本類型,例如3,則無效;不然是引用類型,則返回這個引用類型。


注意第3點了麼?

當new後,this表明新建立的對象。so,咱們能夠利用閉包,在類中聲明一個變量instance來引用建立的實例。而後再重寫類,就OK啦。

以下:

function singletonAccepter( args ){
    var instance = null;
    var args = args || {};
    this.name = args.name || 'Monkey';
    this.age = args.age || 24;
    //將instance引用建立的實例this
    instance = this;
    //重寫構造函數
    singletonAccepter = function(){
        return instance;
    }
};
singletonAccepter.prototype = {
    constructor: singletonAccepter,
    displayInfo: function(){
        console.log('name: ' + this.name + '   age: ' + this.age);
    }
};
相關文章
相關標籤/搜索