国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

《JavaScript設(shè)計(jì)模式》讀后感 覺很復(fù)雜

e10101 / 843人閱讀

摘要:想繼續(xù)了解設(shè)計(jì)模式必須要先搞懂面向?qū)ο缶幊蹋駝t只會(huì)讓你自己更痛苦。創(chuàng)建型設(shè)計(jì)模式主要有簡(jiǎn)單工廠模式,工廠方法模式,抽象工廠模式,建造者模式,原型模式和單例模式,下面一一道來。而工廠方法模式本意是將實(shí)際創(chuàng)建對(duì)象的工作推遲到子類中。

接觸前端兩三個(gè)月的時(shí)候,那時(shí)候只是聽說設(shè)計(jì)模式很重要,然后我就去讀了一本設(shè)計(jì)模式的書,讀了一部分,也不知道這些設(shè)計(jì)模式到底設(shè)計(jì)出來干嘛的,然后就沒再看了。后來就自己做一些小項(xiàng)目也覺著好像不需要用到設(shè)計(jì)模式這個(gè)東西呀。現(xiàn)在,接觸前端有半年了,決定再重新看看設(shè)計(jì)模式,說不定會(huì)有一些啟發(fā)。于是發(fā)現(xiàn)了一本好書——《JavaScript設(shè)計(jì)模式》,寫的通俗易懂,用一個(gè)個(gè)故事串起了一整本書,看了一部分發(fā)現(xiàn)原來我平時(shí)寫代碼的時(shí)候無意之中就用到了一些設(shè)計(jì)模式,然后就忍不住都看完了。看完整本書,讓我完全改變了以前對(duì)設(shè)計(jì)模式的看法,也學(xué)到了很多在實(shí)際項(xiàng)目開發(fā)中的經(jīng)驗(yàn)。這里就簡(jiǎn)單總結(jié)下這本書,也算是做個(gè)筆記,供自己以后參考。(定義一般都比較晦澀難懂,可以先看看使用場(chǎng)景再回來理解相關(guān)定義)
先給個(gè)書的鏈接: JavaScript設(shè)計(jì)模式-張容銘

什么是設(shè)計(jì)模式

設(shè)計(jì)模式是代碼設(shè)計(jì)經(jīng)驗(yàn)的總結(jié),為了可重用代碼,保證代碼的可靠性等。設(shè)計(jì)模式主要分為三大類型,創(chuàng)建型模式,結(jié)構(gòu)型模式和行為型模式,本書還額外寫了另兩類設(shè)計(jì)模式,技巧型模式和架構(gòu)型模式。JavaScript設(shè)計(jì)模式是以面向?qū)ο缶幊虨榛A(chǔ)的,JavaScript的面向?qū)ο缶幊毯蛡鹘y(tǒng)的C++、Java的面向?qū)ο缶幊逃行┎顒e,這讓我一開始接觸JavaScript的時(shí)候感到十分痛苦,但是這只能靠自己慢慢積累慢慢思考。想繼續(xù)了解JavaScript設(shè)計(jì)模式必須要先搞懂JavaScript面向?qū)ο缶幊蹋駝t只會(huì)讓你自己更痛苦。

創(chuàng)建型設(shè)計(jì)模式

創(chuàng)建型設(shè)計(jì)模式是一類處理對(duì)象創(chuàng)建的設(shè)計(jì)模式,通過某種方式控制對(duì)象的創(chuàng)建來避免基本對(duì)象創(chuàng)建時(shí)可能導(dǎo)致設(shè)計(jì)上的問題或增加設(shè)計(jì)上的復(fù)雜度。創(chuàng)建型設(shè)計(jì)模式主要有簡(jiǎn)單工廠模式,工廠方法模式,抽象工廠模式,建造者模式,原型模式和單例模式,下面一一道來。

簡(jiǎn)單工廠模式

作者把簡(jiǎn)單工廠模式比喻成一個(gè)神奇的魔術(shù)師。

定義

又叫靜態(tài)工廠方法,由一個(gè)工廠對(duì)象決定創(chuàng)建某一種產(chǎn)品對(duì)象類的實(shí)例,主要用來創(chuàng)建同一類對(duì)象。

使用場(chǎng)景

看完上面的定義一定很不解,說的到底是啥,現(xiàn)在就舉個(gè)例子來解釋一下。比如體育商品店賣體育器材,里面有很多體育用品及其相關(guān)介紹。當(dāng)你來到體育用品店買一個(gè)籃球,只需問售貨員,他就會(huì)幫你找到你所要的東西。用程序?qū)崿F(xiàn)如下:

// 籃球基類
var Basketball = function() {
    this.intro = "籃球盛行于美國(guó)";
};
Basketball.prototype = {
    getMember: function() {
        console.log("每個(gè)隊(duì)伍需要5名隊(duì)員");
    },
    getBallSize: function() {
        console.log("籃球很大");
    }
};
// 足球基類
var Football = function() {
    this.intro = "足球盛行于美國(guó)";
};
Football.prototype = {
    getMember: function() {
        console.log("每個(gè)隊(duì)伍需要11名隊(duì)員");
    },
    getBallSize: function() {
        console.log("籃球很大");
    }
};
// 運(yùn)動(dòng)工廠
var SportsFactory = function(name) {
    switch(name) {
        case "NBA": 
            return new Basketball();
        case "wordCup": 
            return new Football();
    }
};

當(dāng)你使用這個(gè)運(yùn)動(dòng)工廠時(shí)只需要記住SportsFactory這個(gè)工廠對(duì)象就好了,它會(huì)幫你找到你想要的。
簡(jiǎn)單工廠模式的理念是創(chuàng)建對(duì)象,上面例子是將不同的類實(shí)例化,但是簡(jiǎn)單工廠模式還可以創(chuàng)建相似對(duì)象,將相似的東西提取,不相似的針對(duì)性處理即可。這樣只需創(chuàng)建一個(gè)對(duì)象就可以替代多個(gè)類了。

收獲與總結(jié)

團(tuán)隊(duì)開發(fā)不同于個(gè)人,對(duì)全局變量的限制很大,要盡量少得創(chuàng)建全局變量。如果有同一類對(duì)象在不同需求中重復(fù)使用,那么大部分是不需要重復(fù)創(chuàng)建的,要學(xué)會(huì)代碼復(fù)用。用簡(jiǎn)單工廠來創(chuàng)建對(duì)象,可以減少全局變量創(chuàng)建提高代碼復(fù)用率,它的使用場(chǎng)合限制在創(chuàng)建單一對(duì)象。

工廠方法模式

作者把工廠方法模式比喻成一張名片。

定義

通過對(duì)產(chǎn)品類的抽象使其創(chuàng)建業(yè)務(wù)主要負(fù)責(zé)用于創(chuàng)建多類產(chǎn)品的實(shí)例。

使用場(chǎng)景

在實(shí)際開發(fā)中,需求的變更是很正常的,開始需求簡(jiǎn)單可以直接創(chuàng)建對(duì)象,類似的需求多了可以用簡(jiǎn)單工廠方法重構(gòu),但是如果需求不停變化,那么不僅要修改工廠函數(shù)還要添加類,這樣就沒完了。而工廠方法模式本意是將實(shí)際創(chuàng)建對(duì)象的工作推遲到子類中。

// 工廠類
var Factory = function(type, content) {
    if(this instanceof Factory) {
        var s = new this[type](content);
        return s;
    } else {
        // 防止使用者不知道這是一個(gè)類,忘了加new操作符創(chuàng)建,導(dǎo)致全局變量污染
        return new Factory(type, content);
    }
};
Factory.prototype = {
    Java: function(content) {
        // ...
    },
    JavaScript: function(content) {
        // ...
    },
    php: function(content) {
        // ...
    }
};

這樣以后如果想添加其他類,只需要在Factory的原型里添加就可以了。

收獲與總結(jié)

對(duì)于創(chuàng)建很多類的對(duì)象,簡(jiǎn)單工廠模式就不適合了,通過工廠模式可以輕松創(chuàng)建多個(gè)類的實(shí)例對(duì)象,而且避免了使用者與對(duì)象類之間的耦合,用戶不必關(guān)心創(chuàng)建該對(duì)象的具體類,只需調(diào)用工廠方法即可。

抽象工廠模式

抽象工廠模式讓你感覺出現(xiàn)的都是幻覺。

定義

通過對(duì)類的工廠抽象使其業(yè)務(wù)用于對(duì)產(chǎn)品類簇的創(chuàng)建,而不負(fù)責(zé)某一類產(chǎn)品的實(shí)例。

抽象類

抽象類是一種聲明但不能使用的類,當(dāng)你使用的時(shí)候就會(huì)報(bào)錯(cuò)。JavaScript中的抽象類不能像傳統(tǒng)面向?qū)ο笳Z言那樣輕松地創(chuàng)建,我們可以在類的方法中手動(dòng)拋出錯(cuò)誤來模擬抽象類。你可能會(huì)想,這樣的類什么都不能做能有什么用?其實(shí)它在繼承上是很有用的。

使用場(chǎng)景

抽象工廠模式不能用來創(chuàng)建具體對(duì)象,一般用它作為父類類創(chuàng)建一些子類。

// 抽象工廠方法
var VehicleFactory = function(subType, superType) {
    // 判斷抽象工廠中是否有該抽象類
    if(typeof VehicleFactory[superType] === "function") {
        // 緩存類
        function F() {};
        // 繼承父類屬性和方法
        F.prototype = new VehicleFactory[superType]();
        // 將子類構(gòu)造函數(shù)指向子類
        subType.constructor = subType;
        // 子類原型繼承父類
        subType.prototype = new F();
    } else {
        // 不存在該抽象類拋出錯(cuò)誤
        throw new Error("未創(chuàng)建該抽象類");
    }
};
// 小汽車抽象類
VehicleFactory.Car = function() {
    this.type = "car";
};
VehicleFactory.Car.prototype = {
    getPrice: function() {
        return new Error("抽象方法不能調(diào)用")
    }
};
// 公交車抽象類
VehicleFactory.Bus = function() {
    this.type = "bus";
};
VehicleFactory.Bus.prototype = {
    getPrice: function() {
        return new Error("抽象方法不能調(diào)用");
    }
};

抽象工廠實(shí)際上是一個(gè)子類繼承父類的方法,在該方法中需要通過傳遞子類以及繼承父類的名稱。

收獲與總結(jié)

抽象工廠模式是設(shè)計(jì)模式中最抽象的一種,也是創(chuàng)建模式中唯一一種抽象化創(chuàng)建模式。該模式創(chuàng)建出的結(jié)果不是一個(gè)真實(shí)的對(duì)象實(shí)例,而是一個(gè)類簇,指定了類的結(jié)構(gòu)。

建造者模式

建造者模式告訴我們分即是合。

定義

將一個(gè)復(fù)雜對(duì)象的構(gòu)建層與其表示層相互分離,同樣的構(gòu)建過程可采用不同的表示。

應(yīng)用場(chǎng)景

現(xiàn)在有一個(gè)發(fā)布簡(jiǎn)歷的需求,就是幫別人在公司網(wǎng)站上發(fā)布簡(jiǎn)歷,但是這些簡(jiǎn)歷有一個(gè)需求,除了將興趣愛好以及一些特長(zhǎng)發(fā)布在頁面里,其他信息如聯(lián)系方式等不要發(fā)布在網(wǎng)站上,而且每個(gè)人想找的工作是可以分類的。這樣一些需求我們需要?jiǎng)?chuàng)建的東西就多了,這時(shí)候前面的三種工廠模式都不適合了,這里就可以用建造者模式。
建造者模式和只關(guān)心創(chuàng)建結(jié)果的工廠模式不同,雖然其目的也是創(chuàng)建一個(gè)對(duì)象,但是更多關(guān)心的是創(chuàng)建這個(gè)對(duì)象的整個(gè)過程。在本例中,我們需要的不僅僅是應(yīng)聘者的實(shí)例還要在創(chuàng)建過程中注意這位應(yīng)聘者有哪些興趣愛好等。

// 創(chuàng)建一位人類
var Human = function(param) {
    // 技能
    this.skill = param && param.skill || "保密";
    // 興趣愛好
    this.hobby = param && param.hobby || "保密";
};
// 類人原型方法
Human.prototype = {
    getSkill: function() {
        return this.skill;
    },
    getHobby: function() {
        return this.hobby;
    }
};
// 實(shí)例化姓名類
var Named = function(name) {
    var that = this;
    // 構(gòu)造器,解析姓名的姓與名
    (function(name, that) {
        that.wholeName = name;
        if(name.indexOf(" ") > -1) {
            that.FirstName = name.slice(0, name.indexOf(" "));
            that.FirstName = name.slice(name.indexOf(" "));
        }
    })(name, that);
};
// 實(shí)例化職位類
var Work = function(work) {
    var that = this;
    // 構(gòu)造器,通過傳入的職位特征來設(shè)置相應(yīng)職位及描述
    (function(work, that) {
        switch(work) {
            case "code":
                that.work = "工程師";
                break;
            case "UI":
            case "UE":
                that.work = "設(shè)計(jì)師";
                break;
            case "teach":
                that.work = "教師";
                break;
            default:
                that.work = work;
        }
    })(work, that);
};
// 更換期望的職位
Work.prototype.changeWork = function(work) {
    this.work = work;
};

下面來創(chuàng)建一位應(yīng)聘者

// 應(yīng)聘者創(chuàng)建類
var Person = function(name, work) {
    // 創(chuàng)建應(yīng)聘者緩存對(duì)象
    var _person = new Human();
    // 創(chuàng)建應(yīng)聘者姓名解析對(duì)象
    _person.name = new Named(name);
    // 創(chuàng)建應(yīng)聘者期望職位
    _person.work = new Work(work);
    // 返回創(chuàng)建的應(yīng)聘者對(duì)象
    return _person;
}
收獲與總結(jié)

建造者模式和前面幾種創(chuàng)建型設(shè)計(jì)模式不同,它關(guān)心對(duì)象的整個(gè)創(chuàng)建過程,因此通常將創(chuàng)建對(duì)象的類模塊化,這樣使創(chuàng)建類的每一個(gè)模塊都可以得到靈活的運(yùn)用與高質(zhì)量的復(fù)用。這種方式對(duì)于整個(gè)對(duì)象類的拆分無形中增加了結(jié)構(gòu)的復(fù)雜性,因此如果對(duì)象粒度很小,或者模塊間的復(fù)用率很低,不建議使用建造者模式。

原型模式

原型模式是JavaScript語言之魂。

定義

用原型實(shí)例指向創(chuàng)建對(duì)象的類,使用于創(chuàng)建新的對(duì)象的類共享原型對(duì)象的屬性以及方法。

使用場(chǎng)景

還是關(guān)于子類繼承父類的問題,為了提高性能,對(duì)于每次創(chuàng)建的一些簡(jiǎn)單的而又有差異化的屬性可以放在構(gòu)造函數(shù)中,將一些消耗資源比較大的方法放在基類的原型中,這樣就可以避免不必要的消耗,這就是原型模式的雛形。
原型模式更多的是用在對(duì)象的創(chuàng)建上,比如創(chuàng)建一個(gè)實(shí)例對(duì)象的構(gòu)造函數(shù)比較復(fù)雜或者耗時(shí)比較長(zhǎng),或者通過創(chuàng)建多個(gè)對(duì)象來實(shí)現(xiàn)。此時(shí)最好不要用new關(guān)鍵字去復(fù)制這些基類,可以通過對(duì)這些對(duì)象屬性或者方法進(jìn)行復(fù)制來實(shí)現(xiàn)創(chuàng)建。首先要有一個(gè)原型對(duì)象的復(fù)制方法。

// 原型對(duì)象復(fù)制方法
function prototypeExtend() {
    var F = function() {},
        args = arguments,
        i = 0,
        len = args.length;
    for (; i < len; i++) {
        // 遍歷每個(gè)模板對(duì)象中的屬性
        for(var j in args[i]) {
            F.prototype[j] = args[i][j];
        }
    }
    // 返回緩存類實(shí)例
    return new F();
}

企鵝游戲中創(chuàng)建一個(gè)企鵝對(duì)象,如果沒有企鵝基類,只提供了一些動(dòng)作模板對(duì)象,可以通過實(shí)現(xiàn)這些模板對(duì)象的繼承來創(chuàng)建一個(gè)企鵝實(shí)例對(duì)象。

var penguin = prototypeExtend({
    speed: 20,
    swim: function() {
        console.log("游泳速度" + this.speed);
    },
    run: function() {
        console.log("奔跑速度" + this.speed);
    }
})

這樣通過prototypeExtend創(chuàng)建的就是一個(gè)對(duì)象,不用再用new去創(chuàng)建一個(gè)新的實(shí)例對(duì)象。

收獲與總結(jié)

原型模式實(shí)際上也是一種繼承,可以讓多個(gè)對(duì)象分享同一個(gè)原型對(duì)象的屬性和方法,這種繼承的實(shí)現(xiàn)是不需要?jiǎng)?chuàng)建的,而是將原型對(duì)象分享給那些繼承的對(duì)象。原型對(duì)象更適合在創(chuàng)建復(fù)雜的對(duì)象時(shí),對(duì)于那些需求一直在變化而導(dǎo)致對(duì)象結(jié)構(gòu)不停地改變時(shí),將那些比較穩(wěn)定的屬性與方法共用而提取的繼承的實(shí)現(xiàn)。

單例模式

哈哈,讓你感受下一個(gè)人的寂寞。

定義

又被稱為單體模式,只允許實(shí)例化一次的對(duì)象類。有時(shí)也可以用一個(gè)對(duì)象來規(guī)劃一個(gè)命名空間,井井有條地管理對(duì)象上的屬性和方法。

使用場(chǎng)景

單例模式應(yīng)該是JavaScript中最常見的一種設(shè)計(jì)模式了,經(jīng)常為我們提供一個(gè)命名空間,來防止不同的人命名變量的沖突。還可以用它來創(chuàng)建一個(gè)小型的代碼庫。

var A = {
    Util: {
        util_method1: function() {},
        util_method2: function() {}
    },
    Tool: {
        tool_method1: function() {},
        tool_method2: function() {}
    },
    Ajax: {
        ajax_method1: function() {},
        ajax_method2: function() {}
    }
    ...
}

如果想使用這個(gè)代碼庫,像下面這樣訪問即可:

A.Util.util_method1();
A.Tool.tool_method2();
收獲與總結(jié)

單例模式有時(shí)也被稱為單體模式,它是只允許實(shí)例化一次的對(duì)象類,有時(shí)這么做也是為了節(jié)省系統(tǒng)資源。JavaScript中單例模式經(jīng)常作為命名空間對(duì)象來實(shí)現(xiàn),通過單例對(duì)象,我們可以將各個(gè)模塊的代碼井井有條地梳理在一起。

結(jié)構(gòu)型設(shè)計(jì)模式

結(jié)構(gòu)型設(shè)計(jì)模式關(guān)注于如何將類或?qū)ο蠼M合成更大、更復(fù)雜的結(jié)構(gòu),以簡(jiǎn)化設(shè)計(jì)。主要有外觀模式,適配器模式,代理模式,裝飾者模式,橋接模式,組合模式和享元模式。

外觀模式

作者把這種模式比喻成一種套餐服務(wù)。

定義

為一組復(fù)雜的子系統(tǒng)接口提供一個(gè)更高級(jí)的統(tǒng)一接口,通過這個(gè)接口使得對(duì)子系統(tǒng)接口的訪問更加容易。在JavaScript中有時(shí)也會(huì)用于對(duì)底層結(jié)構(gòu)兼容性做統(tǒng)一封裝來簡(jiǎn)化用戶使用。

使用場(chǎng)景

為頁面文檔document對(duì)象添加點(diǎn)擊事件時(shí),如果直接用onclick來綁定事件,那么如果團(tuán)隊(duì)中再有人要為document綁定click事件時(shí),就會(huì)把之前綁定的那個(gè)時(shí)間覆蓋,因?yàn)檫@是DOM0級(jí)事件。我們應(yīng)該用DOM2級(jí)事件處理程序提供的addEventListener來實(shí)現(xiàn),然而老版本IE是不支持這個(gè)方法的,必須用attachEvent,這樣如果我們寫一個(gè)能兼容所有瀏覽器的方式操作起來就會(huì)更方便,這時(shí)候就可以用到外觀模式。為功能統(tǒng)一但方法不統(tǒng)一的接口提供一個(gè)統(tǒng)一的接口。

// 外觀模式實(shí)現(xiàn)
function addEvent(dom, type, fn) {
    // 對(duì)于支持DOM2級(jí)事件處理程序的瀏覽器
    if(dom.addEventListener) {
        dom.addEventListener(type, fn, false);
    // 對(duì)于不支持addEventListener但支持attachEvent的瀏覽器
    } else if(dom.attachEvent) {
        dom.attachEvent("on" + type, fn);
    } else {
        dom["on" + type] = fn;
    }
}

解決瀏覽器兼容問題只是外觀模式應(yīng)用的一部分,很多代碼庫中都是通過外觀模式來封裝多個(gè)功能,簡(jiǎn)化底層造作方法的。

收獲與總結(jié)

當(dāng)一個(gè)復(fù)雜的系統(tǒng)提供一系列復(fù)雜的接口方法時(shí),為系統(tǒng)的管理方便會(huì)造成接口方法的使用及其復(fù)雜。通過外觀模式,對(duì)接口進(jìn)行二次封裝可以隱藏其復(fù)雜性。

適配器模式

聽到這個(gè)是的名字,有沒有想到水管彎彎的場(chǎng)景呢?

定義

將一個(gè)類(對(duì)象)的接口(方法或者屬性)轉(zhuǎn)化成另外一個(gè)接口,以滿足用戶需求,使類(對(duì)象)之間接口的不兼容問題通過適配器得以解決。

使用場(chǎng)景

公司有個(gè)活動(dòng)頁面正在使用公司內(nèi)部開發(fā)的A框架,可是很多新來的同事使用A框架開發(fā)新的功能需求時(shí)總是感覺很吃力,而且能用的方法有限,為了讓新同事盡快融入項(xiàng)目的開發(fā),可以引入jQuery框架,由于A框架和jQuery框架很像,這樣就可以寫一個(gè)適配器而不需要將之前的代碼全用jQuery寫一遍。
適配器模式不僅在編程中很常見,在生活中這種模式也很常見,比如三角插頭充電器對(duì)于兩項(xiàng)插頭是不能用的,此時(shí)就需要一個(gè)三項(xiàng)轉(zhuǎn)兩項(xiàng)插頭電源適配器,這就是一種適配器模式,其實(shí)它就是為了兩個(gè)代碼庫所寫的代碼兼容運(yùn)行而書寫的額外代碼。
JavaScript中適配器模式還能適配兩個(gè)代碼庫,適配參數(shù),適配數(shù)據(jù),適配服務(wù)端數(shù)據(jù)等。以參數(shù)適配為例。

function doSomeThing(name, title, age, color, size, prize){}

記住這些參數(shù)的順序是很困難的,所以我們經(jīng)常是以一個(gè)參數(shù)對(duì)象方式傳入的,如下所示:

/**
 * obj.name: name
 * obj.title: title
 * obj.age: age
 * obj.color: color
 * obj.size: size
 * obj.prize: prize
***/
function doSomeThing(obj){}

然而當(dāng)調(diào)用的時(shí)候也不能確定傳遞的參數(shù)是否完整,如有一些必須得參數(shù)沒有傳入,一些參數(shù)有默認(rèn)值等,這個(gè)時(shí)候就可以用適配器來適配傳入的參數(shù)對(duì)象。

function doSomeThing(obj) {
    var _adapter = {
        name: "雨夜清荷",
        title: "設(shè)計(jì)模式",
        age: 24,
        color: "pink",
        size: 100,
        prize: 50
    };
    for(var i in _adapter) {
        _adapter[i] = obj[i] || _adapter[i];
    }
}
收獲與總結(jié)

JavaScript中的適配器更多應(yīng)用在對(duì)象之間,為了使對(duì)象可用,通常會(huì)將對(duì)象拆分并重新包裝,這樣就要了解適配器對(duì)象的內(nèi)部結(jié)構(gòu),這也是與外觀模式的區(qū)別所在。

代理模式

有沒有想到牛郎織女鵲橋相會(huì)的場(chǎng)景?

定義

由于一個(gè)對(duì)象不能直接引用另一個(gè)對(duì)象,所以需要通過代理對(duì)象在這兩個(gè)對(duì)象之間起到中介作用。

使用場(chǎng)景

跨域問題應(yīng)該是使用代理模式解決的一個(gè)最典型的問題。由于用戶模塊上傳的照片量越來越大,導(dǎo)致服務(wù)器需要將上傳模塊重新部署到另外一個(gè)域中,這就導(dǎo)致了跨域問題。我們可以將相冊(cè)頁面和上傳模塊所在的服務(wù)器抽象成兩個(gè)對(duì)象,想讓跨域兩端的對(duì)象之間實(shí)現(xiàn)通信,就需要找個(gè)代理對(duì)象來實(shí)現(xiàn)他們之間的通信。
代理對(duì)象有很多種,簡(jiǎn)單一點(diǎn)的如img之類的標(biāo)簽通過src可以向其他域下的服務(wù)器發(fā)送請(qǐng)求。不過這類請(qǐng)求是get請(qǐng)求,是單向的,不會(huì)有響應(yīng)數(shù)據(jù)。另外一種代理對(duì)象的形式是通過script標(biāo)簽。而我們需要的代理對(duì)象,是對(duì)頁面與瀏覽器間通信的,JSONP就實(shí)現(xiàn)了一種代理模式。我們知道src屬性可以實(shí)現(xiàn)get請(qǐng)求,因此可以在src指向的url地址上添加一些字段信息,服務(wù)器獲取這些字段信息,相應(yīng)生成一分內(nèi)容。

// 前端瀏覽器頁面

// 另一個(gè)域下的服務(wù)器請(qǐng)求接口

這種方式可以想象成合理的一只小船,通過小船將你的請(qǐng)求發(fā)送給對(duì)岸,然后對(duì)岸的人們將數(shù)據(jù)放在小船里為你帶回來。

收獲與總結(jié)

代理模式除了在跨域問題中有很多應(yīng)用外,有時(shí)對(duì)對(duì)象的實(shí)例化對(duì)資源的開銷很大,如頁面加載初期加載文件有很多,此時(shí)能夠延遲加載一些圖片對(duì)頁面首屏加載時(shí)間收益是很大的,通過代理可以先加載預(yù)覽圖片然后再加載開銷大的圖片。
由此可見,代理模式可以解決系統(tǒng)之間耦合度以及系統(tǒng)資源開銷大的問題,通過代理對(duì)象可以保護(hù)被代理對(duì)象,使被代理對(duì)象不受外界的影響。

裝飾者模式

顯然房子裝修就是一種典型的裝飾者模式。

定義

在不改變?cè)瓕?duì)象的基礎(chǔ)上,通過對(duì)其進(jìn)行包裝擴(kuò)展(添加屬性或者方法)使原有對(duì)象可以滿足用戶的更復(fù)雜需求。

使用場(chǎng)景

靜止是相對(duì)的,運(yùn)動(dòng)是絕對(duì)的,所以沒有一成不變的需求。在實(shí)際項(xiàng)目開發(fā)中需求總在不斷變化,當(dāng)原有的功能已經(jīng)不能滿足用戶的需求時(shí),我們要做的就是在這個(gè)基礎(chǔ)上添磚加瓦,設(shè)置新功能和屬性來滿足用戶提出的需求,這就是裝飾者模式要做的。

// 裝飾者
var decorator = function(input, fn) {
    // 獲取事件源
    var input = document.getElementById(input);
    // 若事件源已經(jīng)綁定事件
    if(typeof input.onclick === "function") {
        // 緩存事件源原有回調(diào)函數(shù)
        var oldClickFn = input.onclick;
        // 為事件源定義新的事件
        input.onclick = function() {
            // 事件源原有回調(diào)函數(shù)
            oldClickFn();
            // 執(zhí)行事件源新增回調(diào)函數(shù)
            fn();
        }
    } else {
        input.onclick = fn;
    }
}
收獲與總結(jié)

除了裝飾者模式,適配器模式也可以對(duì)原有對(duì)象進(jìn)行擴(kuò)展,所不同的是適配器進(jìn)行擴(kuò)展很多時(shí)候是對(duì)對(duì)象內(nèi)部結(jié)構(gòu)的重組,因此了解其自身結(jié)構(gòu)是必須的。而裝飾者模式對(duì)對(duì)象的擴(kuò)展是一種良性擴(kuò)展,不用了解其具體實(shí)現(xiàn),只是在外部進(jìn)行了一次封裝擴(kuò)展。

橋接模式

作者把這種模式比喻成城市間的公路。

定義

在系統(tǒng)沿著多個(gè)維度變化的同時(shí),又不增加其復(fù)雜度并已達(dá)到解耦。

使用場(chǎng)景

有時(shí)候,頁面中一些小小細(xì)節(jié)的改變常常因邏輯相似而導(dǎo)致大片臃腫的代碼,讓頁面苦澀不堪。現(xiàn)在項(xiàng)目有一個(gè)需求,是要把頁面上部的用戶信息添加一些鼠標(biāo)劃過的特效,但是用戶信息由很多小組件組成,對(duì)于用戶名,鼠標(biāo)劃過直接改變背景色,但是像用戶等級(jí)、用戶消息這類部件只能改變里面的數(shù)字內(nèi)容,處理邏輯不太一樣。這樣就需要寫不少代碼,但是又會(huì)感覺很冗余。這時(shí)候,我們首先要提取共同點(diǎn),對(duì)想的抽象邏輯做抽象提取處理。
對(duì)于用戶信息模塊的每一部分鼠標(biāo)滑過與鼠標(biāo)離開兩個(gè)事件的執(zhí)行函數(shù)有很大一部分是相似的,比如它們都處理每個(gè)部件中的某個(gè)元素,它們都是處理元素的字體顏色和背景顏色。可以創(chuàng)建下面這樣一個(gè)函數(shù),解除this耦合。

function changeColor(dom, color, bg) {
    // 設(shè)置元素的字體顏色
    dom.style.color = color;
    // 設(shè)置元素的背景顏色
    dom.style.background = bg;
}

接下來就是對(duì)具體元素綁定時(shí)間了,但是僅僅知道元素事件綁定與抽象提取的設(shè)置樣式方法changeColor是不夠的,需要用一個(gè)方法將他們鏈接起來,這個(gè)方法就是橋接方法,這種模式就是橋接模式。就像你開著車去沈陽,那么你就需要找到一條連接北京與沈陽的公路,才能順利往返兩地。
對(duì)于事件的橋接方法,可以用一個(gè)匿名函數(shù)來代替。

var spans = document.getElementsByTagName("span");
spans[0].onmouseover = function() {
    changeColor(this, "red", "#ffffd");
}
收獲與總結(jié)

橋接模式最主要的特點(diǎn)是將實(shí)現(xiàn)層(如元素綁定事件)與抽象層(如修飾頁面UI邏輯)解耦分離,使兩部分可以獨(dú)立變化,橋接模式主要是對(duì)結(jié)構(gòu)之間的解耦。

組合模式

作者把組合模式比喻成超值午餐,感覺很形象。

定義

又稱部分-整體模式,將對(duì)象組合成樹形結(jié)構(gòu)以表示“部分整體”的層級(jí)結(jié)構(gòu)。組合模式使得用戶對(duì)單個(gè)對(duì)象和組合對(duì)象的使用具有一致性。

使用場(chǎng)景

為強(qiáng)化首頁用戶體驗(yàn),項(xiàng)目經(jīng)理準(zhǔn)備在用戶首頁添加一個(gè)新聞模塊,當(dāng)然新聞的內(nèi)容是根據(jù)用戶平時(shí)關(guān)注的內(nèi)容挖掘的,因此有的人可能會(huì)顯示文字新聞,有的人可能會(huì)是圖片新聞等等。
我們先來仔細(xì)分析下這個(gè)需求,需求中的這些新聞大致可以分為相互獨(dú)立的幾種類型,對(duì)某類新聞做修改時(shí)不會(huì)影響到其他類的新聞,這樣可以將每一類新聞抽象成面向?qū)ο缶幊讨械囊粋€(gè)類,然后在這些新聞?lì)愔刑暨x一些組合成需要的模塊,這時(shí)候就可以用組合模式了。
在頁面中,組合模式更常用在創(chuàng)建表單上,比如注冊(cè)頁面可能有不同的表單提交模塊。對(duì)于這些需求,我們只需要有一個(gè)基本的個(gè)體,然后通過一定的組合即可實(shí)現(xiàn)。

收獲與總結(jié)

組合模式能夠給我們提供一個(gè)清晰的組成結(jié)構(gòu),組合對(duì)象類通過繼承同一個(gè)父類使其具有統(tǒng)一的方法,這樣也方便了統(tǒng)一管理與使用。

享元模式

作者把享元模式比喻成城市公交車,可以仔細(xì)思考一番。

定義

運(yùn)用共享技術(shù)有效地支持大量的細(xì)粒度的對(duì)象,避免對(duì)象間擁有相同內(nèi)容造成多余的開銷。

使用場(chǎng)景

現(xiàn)在有新聞的內(nèi)容太多,我們有了一個(gè)分頁顯示所有新聞的需求。一個(gè)簡(jiǎn)單直觀的做法就是頁面加載后異步請(qǐng)求新聞數(shù)據(jù),然后創(chuàng)建所有條新聞插入頁面中,需要顯示哪一頁就顯示哪一頁。但是這樣做有一個(gè)很大的問題,這樣一下子創(chuàng)建幾百條新聞同時(shí)插入頁面會(huì)造成多頁的開銷嚴(yán)重影響網(wǎng)頁的性能。這里的所有新聞都有相似的結(jié)構(gòu),只是內(nèi)容不同罷了,對(duì)于這種相同結(jié)構(gòu)造成多余開銷的問題,可以用享元模式來解決。
享元模式 主要是對(duì)其數(shù)據(jù)、方法共享分離,將數(shù)據(jù)和方法分成內(nèi)部數(shù)據(jù)、內(nèi)部方法和外部數(shù)據(jù)、外部方法。內(nèi)部方法與內(nèi)部數(shù)據(jù)指的是相似或共有的數(shù)據(jù)和方法,所以將其提取出來減少開銷。上面例子中,所有新聞個(gè)體都有共同的結(jié)構(gòu),應(yīng)該作為內(nèi)部數(shù)據(jù),而下一頁按鈕綁定的事件則是外部方法。同時(shí)為了使用內(nèi)部數(shù)據(jù)還需要提供一個(gè)操作方法。

var Flyweight = function() {
    // 已創(chuàng)建的元素
    var created = [];
    // 創(chuàng)建一個(gè)新聞包裝容器
    function create() {
        var dom = document.createElement("div");
        // 將容器插入新聞列表容器中
        document.getElementById("container").appendChild(dom);
        // 緩存新創(chuàng)建的元素
        created.push(dom);
        // 返回創(chuàng)建的新元素
        return dom;
    }
    return {
        // 獲取創(chuàng)建新聞元素方法
        getDiv: function() {
            // 如果已創(chuàng)建的元素小于當(dāng)前頁元素總個(gè)數(shù)(5個(gè)),則創(chuàng)建
            if(created.length < 5) {
                return created();
            } else {
                // 獲取第一個(gè)元素,并插入去后面
                var div = created.shift();
                created.push(div);
                return div;
            }
        }
    }
}

上面創(chuàng)建一個(gè)享元類,由于每頁只能顯示5條新聞,所以創(chuàng)建5個(gè)元素,保存在享元類內(nèi)部,可以通過getDiv方法來獲取創(chuàng)建的元素。下面就要實(shí)現(xiàn)外部數(shù)據(jù)和外部方法,外部數(shù)據(jù)就是我們要顯示的所有新聞內(nèi)容,由于每個(gè)內(nèi)容都不一樣肯定不能共享。首先,我們要根據(jù)新聞內(nèi)容實(shí)例化頁面,然后,對(duì)下一頁綁定一個(gè)點(diǎn)擊事件,顯示下一頁。

var paper = 0,
    num = 5,
    len = article.length;
// 添加五條新聞
for(var i = 0; i < 5; i++) {
    if(article[i])
        // 通過享元類獲取創(chuàng)建的元素并寫入新聞內(nèi)容
        Flyweight.getDiv().innerHTML = article[i];
}
// 下一頁按鈕綁定事件
document.getElementById("next_page").onclick = function() {
    // 如果新聞內(nèi)容不足5條則返回
    if(article.length < 5) {
        return;
    }
    var n = ++paper * num % len,  // 獲取當(dāng)前頁的第一條新聞索引
        j = 0;
    // 插入5條新聞
    for(; j < 5; j++) {
        // 如果存在n+j條則插入
        if(article[n + j]) {
            Flyweight.getDiv().innerHTML = article[n + j];
        // 否則插入起始位置第n+j-len條
        } else if(article[n + j - len]) {
            Flyweight.getDiv().innerHTML = article[n + j - len];
        } else {
            Flyweight.getDiv().innerHTML = "";
        }
    }
}

這樣用享元模式對(duì)頁面重構(gòu)之后每次操作只需要操作5個(gè)元素,這樣性能可以提高很多。

收獲與總結(jié)

享元模式的應(yīng)用是為了提高程序的執(zhí)行效率與系統(tǒng)性能,因此在大型系統(tǒng)開發(fā)中應(yīng)用比較廣泛,可以避免程序中的數(shù)據(jù)重復(fù)。應(yīng)用時(shí)一定要找準(zhǔn)內(nèi)部狀態(tài)與外部狀態(tài),這樣才能更合理地提取分離。

行為型設(shè)計(jì)模式

行為型設(shè)計(jì)模式用于不同對(duì)象之間職責(zé)劃分或算法抽象,行為型設(shè)計(jì)模式不僅僅涉及類和對(duì)象,還涉及類或?qū)ο笾g的交流模式并加以實(shí)現(xiàn)。行為型設(shè)計(jì)模式主要有模板方法模式,觀察者模式,狀態(tài)模式,策略模式,職責(zé)鏈模式,命令模式,訪問者模式,中介者模式,備忘錄模式,迭代器模式和解釋器模式,這么多的模式真得好好消化一陣子了。

模板方法模式

作者把這種模式比喻成照貓畫虎。

定義

父類中定義一組操作算法骨架,而將一些實(shí)現(xiàn)步驟延遲到子類,使得子類可以不改變父類算法結(jié)構(gòu)的同時(shí)可重新定義算法中某些實(shí)現(xiàn)步驟。

使用場(chǎng)景

提示框歸一化,一個(gè)網(wǎng)站有很多頁面,如果每個(gè)頁面的彈出框樣式不太一致就會(huì)顯得不是很和諧,需要將他們的樣式統(tǒng)一。新手最直觀的想法就是去每個(gè)頁面一個(gè)個(gè)修改,當(dāng)然這樣的代價(jià)是很大的,我們需要寫一個(gè)彈出框插件,將這些彈出框封裝好,然后再各個(gè)頁面調(diào)用即可。這是在這個(gè)插件中就可以使用模板方法模式了,不需要重復(fù)寫多個(gè)樣式。
模板方法模式就是將多個(gè)模型抽象畫歸一,從中抽象出一個(gè)最基本的模板,這個(gè)模板可以作為實(shí)體也可以作為抽象對(duì)象,其他模塊只需要繼承這個(gè)模板方法,也可以擴(kuò)展某些方法。
打個(gè)比方,我們生活中用蛋糕做模具做蛋糕,做出的蛋糕是外形相同的,因?yàn)樗麄兌加猛粋€(gè)模具。然而商店里面賣的蛋糕是各式各樣的,這都是對(duì)蛋糕的二次加工。我們的需求中基本提示框就是我們抽象出來的模具,其他提示框比這個(gè)提示框要多一些功能,我們只需要對(duì)他們做一些二次加工就能滿足需求了。
模板方法不僅在歸一化組件時(shí)使用,有時(shí)候創(chuàng)建頁面時(shí)也是很常用的,比如創(chuàng)建三類導(dǎo)航,第一類是基礎(chǔ)的,第二類是多了消息提醒功能的,第三類多了后面顯示網(wǎng)址功能。這也可以用模板方法實(shí)現(xiàn),此時(shí)抽象出來的基類是最簡(jiǎn)單的基礎(chǔ)導(dǎo)航類。

// 格式化字符串方法
function formateString(str, data) {
    return str.replace(/{#(w+)#}/g, function(match, key) {
        return typeof data[key] === undefined ? "": data[key]
    });
}
// 基礎(chǔ)導(dǎo)航
var Nav = function(data) {
    // 基礎(chǔ)導(dǎo)航樣式模板
    this.item = "{#name#}";
    // 創(chuàng)建字符串
    this.html = "";
    // 格式化數(shù)據(jù)
    for(var i = 0, len = data.length; i < len; i++) {
        this.html += formateString(this.item, data[i]);
    }
    // 返回字符串?dāng)?shù)據(jù)
    return this.html;
}

對(duì)于消息提醒導(dǎo)航類,只需額外添加消息提醒組件模板,并與消息提醒組件模板對(duì)傳入的網(wǎng)址數(shù)據(jù)進(jìn)行裝飾,得到所需的字符串,在調(diào)用從基類繼承的方法處理這些字符串即可。

var NumNav = function(data) {
    // 消息提醒信息組件模板
    var tpl = "{#num#}";
    // 裝飾數(shù)據(jù)
    for(var i = data.length - 1; i >= 0; i--) {
        data[i].name += data[i].name + formateString(tpl, data[i]);
    }
    // 繼承基礎(chǔ)導(dǎo)航類
    return Nav.call(this, data);
}
收獲與總結(jié)

模板方法的核心在于對(duì)方法的重用,將核心方法封裝在基類中,讓子類繼承基類的方法,實(shí)現(xiàn)基類方法的共享,達(dá)到方法共用。子類繼承的方法是可擴(kuò)展的,這就需要對(duì)基類繼承的方法進(jìn)行重寫。

觀察者模式

作者把這種模式比喻成通信衛(wèi)星。

定義

又被稱作發(fā)布-訂閱模式或消息機(jī)制,定義了一種依賴關(guān)系,解決了主體對(duì)象與觀察者之間功能的耦合。

使用場(chǎng)景

在團(tuán)隊(duì)開發(fā)中,經(jīng)常是一個(gè)人負(fù)責(zé)一個(gè)模塊,那么每人負(fù)責(zé)的模塊之間要如何進(jìn)行溝通呢?比如你實(shí)現(xiàn)一些需求需要添加一些代碼,但是這個(gè)需求需要其他模塊配合,但是每個(gè)模塊都是不同人寫的,你不想因?yàn)樾绿砑拥拇a影響到他人實(shí)現(xiàn)的功能,這個(gè)時(shí)候就需要用到觀察者模式了。
觀察者模式就是為了解決主體對(duì)象與觀察者之間的耦合。打個(gè)比方,目前每個(gè)國(guó)家都在研發(fā)并發(fā)射衛(wèi)星,發(fā)射這些衛(wèi)星是為了監(jiān)控一些信息,那么它就可以被看做一個(gè)觀察者或者說是一個(gè)消息系統(tǒng),如果讓這顆衛(wèi)星為飛機(jī)導(dǎo)航,那么這架飛機(jī)就是一個(gè)被觀察者或者說是一個(gè)主體對(duì)象。那么如果地面上的中轉(zhuǎn)站或者其他飛機(jī)需要知道這架飛機(jī)的信息,于是每當(dāng)飛機(jī)到達(dá)一個(gè)地方時(shí)就會(huì)向衛(wèi)星發(fā)出位子信息,然后衛(wèi)星又將信息廣播到已經(jīng)訂閱這架飛機(jī)的中轉(zhuǎn)站,這樣就可以避免一些飛機(jī)事故發(fā)生。
這時(shí)候,觀察者至少需要有兩個(gè)方法,一個(gè)是接收某架飛機(jī)發(fā)來的消息,一個(gè)是向訂閱的中轉(zhuǎn)站發(fā)送響應(yīng)消息。但是,并不是每個(gè)中轉(zhuǎn)站都要時(shí)刻監(jiān)控飛機(jī)狀態(tài)的,所以還需要一個(gè)取消注冊(cè)的方法。當(dāng)然這些消息還需要保存,就需要一個(gè)保存消息的容器。這時(shí)候觀察者雛形就出來了,他有一個(gè)消息容器和三個(gè)方法,訂閱消息方法,取消訂閱消息方法,發(fā)送訂閱消息方法。

var Observer = (function() {
    // 防止消息隊(duì)列暴露而被篡改,故將消息容器作為靜態(tài)私有變量保存
    var __messages = {};
    return {
        // 注冊(cè)信息接口
        regist: function() {},
        // 發(fā)布信息接口
        fire: function() {},
        // 移除信息接口
        remove: function() {}
    }
})();

下面就是可以自己具體實(shí)現(xiàn)這些接口了。

收獲與總結(jié)

觀察者模式最主要是解決類或?qū)ο笾g的耦合,解耦兩個(gè)互相依賴的對(duì)象,使其依賴于觀察者的消息機(jī)制。這樣對(duì)于任何一個(gè)訂閱者來說,其他訂閱者對(duì)象的改變不會(huì)影響到自身,其自身既可以是消息的發(fā)出者也可以是消息的執(zhí)行者,這都依賴于調(diào)用觀察者對(duì)象中的三種方法(訂閱,注銷,發(fā)布消息)中的哪一種。

狀態(tài)模式

作者把這種模式比喻成超級(jí)瑪麗。

定義

當(dāng)一個(gè)對(duì)象內(nèi)部狀態(tài)發(fā)生改變時(shí),會(huì)導(dǎo)致其行為的改變,這看起來像是改變了對(duì)像。

使用場(chǎng)景

平時(shí)寫代碼的時(shí)候經(jīng)常會(huì)遇到要寫很多條件判斷語句的情況,那么怎么減少代碼中的條件判斷語句呢?對(duì)于這類分支條件內(nèi)部獨(dú)立結(jié)果的管理,可以使用狀態(tài)模式,每一種條件作為對(duì)象的一種狀態(tài),面對(duì)不同的判斷結(jié)果,其實(shí)就是選擇對(duì)象內(nèi)的一種狀態(tài)。
將不同的判斷結(jié)果封裝在狀態(tài)對(duì)象內(nèi),然后該狀態(tài)對(duì)象返回一個(gè)可被調(diào)用的接口方法,用于調(diào)用狀態(tài)對(duì)象內(nèi)部的某種方法。

// 投票結(jié)果狀態(tài)對(duì)象
var ResultState = function() {
    // 判斷結(jié)果保存在內(nèi)部狀態(tài)中
    var States = {
        // 每種狀態(tài)作為一種獨(dú)立方法保存
        state0: function() {
            console.log("這是第一種情況"):
        },
        state1: function() {
            console.log("這是第二種情況"):
        },
        state2: function() {
            console.log("這是第三種情況"):
        },
        state3: function() {
            console.log("這是第四種情況"):
        }
    }
    // 獲取某種狀態(tài)并執(zhí)行對(duì)應(yīng)方法
    function show(result) {
        States["state" + result] && States["state" + result]();
    }
    return {
        // 返回調(diào)用狀態(tài)方法接口
        show: show
    }
}();

想調(diào)用第三種結(jié)果就可以如下調(diào)用

ResultState.show(3);

對(duì)于狀態(tài)模式,主要目的就是將條件判斷的不同結(jié)果轉(zhuǎn)化為狀態(tài)對(duì)象的內(nèi)部狀態(tài),這個(gè)內(nèi)部狀態(tài)一般作為狀態(tài)對(duì)象的私有變量,然后提供一個(gè)能夠調(diào)用狀態(tài)對(duì)象內(nèi)部狀態(tài)的接口方法對(duì)象即可。

收獲與總結(jié)

狀態(tài)模式既是解決程序中臃腫的分支判斷語句問題,將每一個(gè)分支轉(zhuǎn)化為一種狀態(tài)獨(dú)立出來,方便每種狀態(tài)的管理又不至于每次只需時(shí)遍歷所有分支。

策略模式

作者把這種模式比喻成活諸葛。

定義

將定義的一組算法封裝起來,使其相互之間可以替換。封裝的算法具有一定獨(dú)立性,不會(huì)隨客戶端變化而變化。

使用場(chǎng)景

年底的時(shí)候,公司商品展銷頁都要開展大促銷活動(dòng)。在圣誕節(jié),一部分商品5折出售,一部分商品8折出售,一部分商品9折出售,到元旦搞個(gè)幸運(yùn)反饋活動(dòng),普通用戶滿100返30,高級(jí)VIP用戶滿100返50。這個(gè)時(shí)候上面的狀態(tài)模式就不適用了,因?yàn)槊恳惶烀恳粋€(gè)商品只有一種促銷情況,這個(gè)時(shí)候可以用策略模式。
結(jié)構(gòu)上看,它與狀態(tài)模式很像,也是在內(nèi)部封裝一個(gè)對(duì)象,然后通過返回的接口對(duì)象實(shí)現(xiàn)實(shí)現(xiàn)對(duì)內(nèi)部對(duì)象的調(diào)用,不同點(diǎn)是,策略模式不需要管理狀態(tài)、狀態(tài)間沒有依賴關(guān)系、策略之劍可以相互替換、在策略對(duì)象內(nèi)部保存的是相互獨(dú)立的一些算法。看看策略對(duì)象的實(shí)現(xiàn):

// 價(jià)格策略對(duì)象
var PriceStrategy = function() {
    // 內(nèi)部算法對(duì)象
    var strategy = {
        // 100返30
        return30: function(price) {},
        // 100返50
        return50: function(price) {},
        // 9折
        percent90: function(price) {},
        // 8折
        percent80: function(price) {},
        // 5折
        percent50: function(price) {},
    }
    // 策略算法調(diào)用接口
    return function(algorithm, price) {
        return strategy[algorithm] && strategy[algorithm](price);
    }
}();
收獲與總結(jié)

策略模式主要特色是創(chuàng)建一系列策略算法,每組算法處理業(yè)務(wù)都是相同的,只是處理的過程或者處理的結(jié)果不一樣,所以它們是可以相互替換的,這樣就解決了算法與使用者之間的耦合。

職責(zé)鏈模式

作者把這種模式比喻成一個(gè)有序車站。

定義

解決請(qǐng)求的發(fā)送者與請(qǐng)求的接受者之間的耦合,通過職責(zé)鏈上的多個(gè)對(duì)象對(duì)分解請(qǐng)求流程,實(shí)現(xiàn)請(qǐng)求在多個(gè)對(duì)象之間的傳遞,知道最后一個(gè)對(duì)象完成請(qǐng)求的處理。

使用場(chǎng)景

項(xiàng)目經(jīng)理準(zhǔn)備改善頁面中的輸入驗(yàn)證與提示交互體驗(yàn)。如用戶在輸入框輸入信息后,在輸入框的下面提示出一些備選項(xiàng),當(dāng)用戶輸入完成后,則要對(duì)用戶輸入信息進(jìn)行驗(yàn)證等,頁面中很多模塊需要用戶提交信息,為增強(qiáng)用戶體驗(yàn),這些輸入框大部分需要具備以上兩種功能。現(xiàn)在需要完成這個(gè)需求,但是以后可能要對(duì)原有表單交互體驗(yàn)做一些修改,也就是這是一個(gè)半成品需求。這種情況下,我們需要將需求里面需要做的每一件事情獨(dú)立出來,這樣完整的需求就變成一個(gè)個(gè)相互獨(dú)立的模塊需求,這樣就不會(huì)因?yàn)橐院笮枨蟮母淖兌绊懳覀冺?xiàng)目的進(jìn)展,這樣還有利于以后的單元測(cè)試。這其實(shí)就是一種職責(zé)鏈模式。
對(duì)于上面的需求,對(duì)輸入框綁定事件是第一部分,第二部分是創(chuàng)建xhr進(jìn)行異步數(shù)據(jù)獲取,第三部分就是適配響應(yīng)數(shù)據(jù),將接收到的數(shù)據(jù)格式化成可處理的形式,最后一部分是向組件創(chuàng)建器傳入相應(yīng)數(shù)據(jù)生成組件。

收獲與總結(jié)

職責(zé)鏈模式定義了請(qǐng)求的傳遞方向,通過多個(gè)對(duì)象對(duì)請(qǐng)求的傳遞,實(shí)現(xiàn)一個(gè)復(fù)雜的邏輯操作。因此職責(zé)鏈模式將負(fù)責(zé)的需求顆粒化逐一實(shí)現(xiàn)每個(gè)最小分內(nèi)的需求,并將請(qǐng)求順序地傳遞。對(duì)于職責(zé)鏈上的每一個(gè)對(duì)象來說,它可能是請(qǐng)求的發(fā)起者也可能是請(qǐng)求的接收者,通過這種方式不僅僅簡(jiǎn)化原對(duì)象的復(fù)雜度,而且解決原請(qǐng)求的發(fā)起者與原請(qǐng)求的接收者之間的耦合。

命令模式 定義

將請(qǐng)求與實(shí)現(xiàn)解耦并封裝成獨(dú)立對(duì)象,從而使不同的請(qǐng)求對(duì)客戶端的實(shí)現(xiàn)參數(shù)化。

使用場(chǎng)景

現(xiàn)在的需求是要做一個(gè)活動(dòng)頁面,平鋪式的結(jié)構(gòu),不過頁面的每個(gè)模塊都有些相似的地方,比如每個(gè)預(yù)覽產(chǎn)品圖片區(qū)域,都有一行標(biāo)題,然后標(biāo)題下面是產(chǎn)品圖片,只是圖片的數(shù)量與排列不同。我們需要一種自由創(chuàng)建視圖模塊的方法,有時(shí)候創(chuàng)建多張圖片有時(shí)候只創(chuàng)建一張圖片,這時(shí)候可以試試命令模式。
命令模式是將創(chuàng)建模塊的邏輯封裝在一個(gè)對(duì)象里,這個(gè)對(duì)象提供一個(gè)參數(shù)化的請(qǐng)求接口,通過調(diào)用這個(gè)接口并傳遞一些參數(shù)實(shí)現(xiàn)調(diào)用命令對(duì)象內(nèi)部中的一些方法。請(qǐng)求部分很簡(jiǎn)單,只需要按照給定參數(shù)格式書寫指令即可,所以實(shí)現(xiàn)部分的封裝才是重點(diǎn),因?yàn)樗獮檎?qǐng)求部分提供所需方法。
那么哪些對(duì)象需要被命令化呢?既然需要?jiǎng)討B(tài)展示不同模塊,所以創(chuàng)建元素這一需求就是變化的,因此創(chuàng)建元素方法、展示方法應(yīng)該被命令化。

// 模塊實(shí)現(xiàn)模塊
var viewCommand = (function() {
    var tpl = {
        // 展示圖片結(jié)構(gòu)模塊
        product: [
            "
",.....,"
" ].join(""), // 展示標(biāo)題結(jié)構(gòu)模塊 title: [ "
",.....,"
" ].join(""), }, // 格式化字符串緩存字符串 html = ""; // 格式化字符串 function formateString(str, obj) {} // 方法集合 var Action = { // 創(chuàng)建方法 create: function(data, view) { // 解析數(shù)據(jù) if(data.length) { // 遍歷 for(var i = 0, len = data.length; i < len; i++) { html += formateString(tpl[view], data[i]); } } else { html += formateString(tpl[view], data); } }, // 展示方法 display: function(container, data, vuew) { // 如果傳入數(shù)據(jù) if(data) { // 根據(jù)給的數(shù)據(jù)創(chuàng)建視圖 this.create(data, view); } // 展示模塊 document.getElementById(container).innerHTML = html; // 展示后清空緩存字符串 html = ""; } } // 命令接口 return function excute(msg) { // 解析命令,如果msg.param不是數(shù)組則將其轉(zhuǎn)化為數(shù)組 msg.param = Object.prototype.toString.call(msg.param) === "[object Array]" ? msg.param : [msg.param]; // Action內(nèi)部調(diào)用的方法引用this,此處保證作用域this執(zhí)行傳入Action Action[msg.command].apply(Action, msg.param) } })();

下面就可以測(cè)試這個(gè)命令對(duì)象了:

var productData = [
    {
        src: "command/02.jpg",
        text: "綻放的桃花"
    },
    {
        src: "command/03.jpg",
        text: "陽光下的溫馨"
    }
],
// 模塊標(biāo)題數(shù)據(jù)
titleData = {
    title: "夏日里的一片溫馨",
    tips: "暖暖的溫情帶給人們家的感覺"
}
// 調(diào)用命令對(duì)象
viewCommand({
    command: "display",
    param: ["title", titleData, "title"]
});
viewCommand({
    command: "create",
    param: ["product", productData, "product"]
});

有了命令模式,想創(chuàng)建任何頁面視圖都是一件很簡(jiǎn)單的事情。

收獲與總結(jié)

命令模式是將執(zhí)行的命令封裝,解決命令發(fā)起者與命令執(zhí)行者之間的耦合,每一條命令實(shí)質(zhì)上是一個(gè)操作。命令的是使用者不必了解命令執(zhí)行者的命令接口是如何實(shí)現(xiàn)的,只需要知道如何調(diào)用。

訪問者模式

作者把這種模式比喻成駐華大使。

定義

針對(duì)于對(duì)象結(jié)構(gòu)中的元素,定義在不改變對(duì)象的前提下訪問結(jié)構(gòu)中元素的新方法。

使用場(chǎng)景

用DOM2級(jí)事件為頁面中元素綁定事件時(shí),為css設(shè)置一些樣式如下:

var bindEvent = function(dom, type, fn) {
    if(dom.addEventListener) {
        dom.addEventListener(type, fn, false);
    } else if(dom.attachEvent) {
        dom.attachEvent("on" + type, fn);
    } else {
        dom["on" + type] = fn;
    }
}
var demo = document.getElementById("demo");
bindEvent(demo, "click", function() {
    this.style.background = "red";
});

這個(gè)在IE瀏覽器中會(huì)出問題,因?yàn)镮E的attachEvent事件中this指向的竟然是window而不是這個(gè)元素,所以如果想獲取事件對(duì)象必須用window.e來獲取。這個(gè)問題可以借用訪問者模式來解決。
訪問者模式的思想是我們?cè)诓桓淖儾僮鲗?duì)象的同時(shí),為它添加新的操作方法,來實(shí)現(xiàn)對(duì)操作對(duì)象的訪問。下面看看IE的實(shí)現(xiàn)方式:

function bindIEEvent(dom, type, fn, data) {
    var data = data || {};
    dom.attachEvent("on" + type, function(e){
        fn.call(dom, e, data);
    });
};

上面實(shí)現(xiàn)方法的核心就是調(diào)用call方法,call方法的作用就是更改函數(shù)執(zhí)行時(shí)的作用域,這正是訪問者模式的精髓。

收獲與總結(jié)

訪問者模式解決數(shù)據(jù)與數(shù)據(jù)操作方法之間的耦合,將數(shù)據(jù)的操作方法獨(dú)立于數(shù)據(jù),使其可以自由化演變。訪問者更適合那些數(shù)據(jù)穩(wěn)定但是數(shù)據(jù)的操作方法易變的環(huán)境下。

中介者模式

作者把這種模式比喻成媒婆,好吧,我笑了這里。

定義

通過中介者對(duì)象封裝一系列對(duì)象之間的交互,是對(duì)象之間不再相互引用,降低他們之間的耦合。有時(shí)中介者對(duì)象也可以改變對(duì)象之間的交互。

使用場(chǎng)景

項(xiàng)目經(jīng)理準(zhǔn)備在用戶首頁上的導(dǎo)航模塊添加一個(gè)設(shè)置層,讓用戶可以通過設(shè)置層來設(shè)置導(dǎo)航展開樣式。但是頁面中好多模塊都有導(dǎo)航,這要改起來工作量也很大,上面講的觀察者模式雖然能解決模塊之間的耦合,但是這里我們并沒有需要向設(shè)置層發(fā)送請(qǐng)求的需求,設(shè)置層只是單向控制導(dǎo)航模塊內(nèi)導(dǎo)航的樣式。這樣的單向通信就可以使用中介者模式。
觀察者模式和中介者模式都是通過消息收發(fā)機(jī)制實(shí)現(xiàn),不過在觀察者模式中,一個(gè)對(duì)象既可以是消息的發(fā)送者也可以是消息的接收者,而中介者模式中消息的發(fā)送方只有一個(gè)就是中介者對(duì)象,而且中介者對(duì)象不能訂閱消息,只有那些活躍對(duì)象(訂閱者)才能訂閱中介者消息。
如果用中介者模式來解決上面的問題,那么中介者對(duì)象就是設(shè)置層模塊對(duì)象,它負(fù)責(zé)向各個(gè)導(dǎo)航模塊對(duì)象發(fā)送用戶設(shè)置消息,而各個(gè)導(dǎo)航模塊則應(yīng)該作為消息的訂閱者存在,實(shí)現(xiàn)如下:

// 中介者對(duì)象
var Mediator = function() {
    // 消息對(duì)象
    var _msg = {};
    return {
        // 訂閱消息方法,type:消息名稱 action:消息回調(diào)函數(shù)
        register: function(type, action) {
            // 如果消息存在
            if(_msg[type])
                // 存入回調(diào)函數(shù)
                _msg[type].push(action);
            else {
                // 不存在則建立消息容器
                _msg[type] = [];
                _msg[type].push(action);
            }
        },
        // 發(fā)布消息方法
        send: function(type) {
            // 如果該消息已經(jīng)被訂閱
            if(_msg[type]) {
                // 遍歷已存儲(chǔ)的消息回調(diào)函數(shù)
                for(var i = 0, len = _msg[type].length; i < len; i++) {
                    // 執(zhí)行回調(diào)函數(shù)
                    _msg[type][i] && _msg[type][i]();
                }
            }
        }
    }
}();

這樣就創(chuàng)建了一個(gè)中介者對(duì)象,下面就可以利用這個(gè)中介者對(duì)象完成我們的需求了。

收獲與總結(jié)

同觀察者模式一樣,中介者模式的主要業(yè)務(wù)也是通過模塊間或者對(duì)象間的復(fù)雜通信,來解決模塊間或?qū)ο箝g的耦合。在中介者模式中,訂閱者是單向的,只能是訂閱者而不能是發(fā)布者。而消息統(tǒng)一由中介者對(duì)象發(fā)布。

備忘錄模式 定義

在不破壞對(duì)象的封裝性的前提下,在對(duì)象之外捕獲并保存該對(duì)象內(nèi)部狀態(tài)以便日后對(duì)象使用或者對(duì)象恢復(fù)到以前的某個(gè)狀態(tài)。

使用場(chǎng)景

在前面提到的新聞頁面中,有上一頁和下一頁的按鈕,頁面的內(nèi)容是用異步請(qǐng)求獲取的。如果點(diǎn)擊下一頁按鈕接著再點(diǎn)擊上一頁那么之前那一頁又要進(jìn)行一次異步請(qǐng)求,這是多余的操作。因?yàn)榈谝淮我呀?jīng)獲取了數(shù)據(jù),不需要再發(fā)送多余的請(qǐng)求。這個(gè)時(shí)候可以用備忘錄模式來緩存請(qǐng)求過的數(shù)據(jù)。也就是說每次發(fā)生請(qǐng)求的時(shí)候?qū)Ξ?dāng)前狀態(tài)做一次記錄,將請(qǐng)求到的數(shù)據(jù)以及對(duì)應(yīng)得頁碼緩存下來,如果之后返回到之前瀏覽過的頁面,直接在緩存中查詢即可,不用發(fā)生異步請(qǐng)求。先創(chuàng)建一個(gè)新聞緩存器:

// Page備忘錄類
var Page = function() {
    // 信息緩存對(duì)象
    var cache = {};
    return function(page, fn) {
        // 判斷該頁數(shù)據(jù)是否在緩存中
        if(cache[page]) {
            // 顯示該頁內(nèi)容
            showPage(page, cache[page]);
            // 執(zhí)行成功回調(diào)函數(shù)
            fn && fn();
        } else {
            // 否則異步請(qǐng)求
            $.post("./data/getNewsData.php", {
                page: page
            }, function(res) {
                // 成功返回
                if(res.errNo == 0) {
                    showPage(page, res.data);
                    cache[page] = res.data;
                    fn && fn();
                } else {
                    // 處理異常
                }
            })
        }
    }
}

上面代碼可以看出Page緩存器內(nèi)部緩存了每次請(qǐng)求回來的新聞數(shù)據(jù),這樣以后如果用戶想回看某頁新聞數(shù)據(jù)就不需要發(fā)送不必要的請(qǐng)求了。

收獲與總結(jié)

備忘錄模式最主要的任務(wù)是對(duì)現(xiàn)有的數(shù)據(jù)或狀態(tài)進(jìn)行緩存,為將類某個(gè)時(shí)刻使用或恢復(fù)做準(zhǔn)備。但是當(dāng)數(shù)據(jù)量過大時(shí),會(huì)嚴(yán)重占用系統(tǒng)提供的資源,此時(shí)對(duì)緩存器的優(yōu)化是很有必要的,復(fù)用率低的數(shù)據(jù)緩存下來是不值得的。

迭代器模式

作者把這種模式比喻成一個(gè)點(diǎn)鈔機(jī)。

定義

在不暴露對(duì)象內(nèi)部結(jié)構(gòu)的同時(shí),可以順序地訪問聚合對(duì)象內(nèi)部的元素。

使用場(chǎng)景

迭代器模式主要是解決重復(fù)循環(huán)迭代的問題,之前接觸過面向?qū)ο笳Z言的應(yīng)該都對(duì)迭代器有所了解。迭代器就是用來順序地訪問一個(gè)聚合對(duì)象內(nèi)部元素的,它可以簡(jiǎn)化我們遍歷操作,就行銀行里的點(diǎn)鈔機(jī),有了它可以大幅度降低我們的點(diǎn)鈔成本。下面創(chuàng)建一個(gè)常用的迭代器對(duì)象:

var Iterator = function(items, container) {
    // 獲取父元素
    var container = container && document.getElementById(container) || document,
    // 獲取元素
        items = container.getElementsByTagName(items),
    // 獲取元素長(zhǎng)度
        length = items.length,
    // 當(dāng)前索引值
        index = 0;
    // 緩存原生數(shù)組splice方法
    var splice = [].splice;
    return {
        // 獲取第一個(gè)元素
        first: function() {},
        // 獲取最后一個(gè)元素
        second: function() {},
        // 獲取前一個(gè)元素
        pre: function() {},
        // 獲取后一個(gè)元素
        next: function() {},
        // 獲取某一個(gè)元素
        get: function(num) {},
        // 對(duì)每一個(gè)元素執(zhí)行某一個(gè)方法
        dealEach: function(fn) {},
        // 對(duì)某一個(gè)元素執(zhí)行某一個(gè)方法
        dealItem: function(num, fn) {},
        // 排他方式處理某一個(gè)元素
        exclusive: function() {}
    }
}

下面具體實(shí)現(xiàn)迭代器里面的這些方法,然后就可以用這個(gè)迭代器對(duì)象啦。

收獲與總結(jié)

通過迭代器我們可以順序地訪問一個(gè)聚合對(duì)象中的每一個(gè)元素。在開發(fā)中,迭代器極大簡(jiǎn)化了代碼中的循環(huán)語句,使代碼結(jié)構(gòu)清晰緊湊。用迭代器去處理一個(gè)對(duì)象時(shí),只需要提供處理的方法,而不必去關(guān)心對(duì)象的內(nèi)部結(jié)構(gòu),這也解決了對(duì)象的使用者與對(duì)象內(nèi)部結(jié)構(gòu)之間的耦合。

解釋器模式 定義

對(duì)于一種語言,給出其文法表示,并定義一種解釋器,通過使用這種解釋器來解釋語言中定義的句子。

使用場(chǎng)景

一個(gè)頁面中的某些功能好壞有時(shí)是靠一定的數(shù)據(jù)依據(jù)支撐的。項(xiàng)目經(jīng)理想看看用戶對(duì)最近新增的功能使用情況,前后端要給出統(tǒng)計(jì)數(shù)據(jù),然而前端交互統(tǒng)計(jì)項(xiàng)中要給出交互元素路徑。這件事情與冒泡事件類似,只不過在這個(gè)路徑中還要關(guān)心同一層級(jí)中當(dāng)前元素的兄弟元素。比如下面的結(jié)構(gòu):

要獲取button相對(duì)于class為wrap的div元素的Xpath路徑,那么可以表示為DIV>DIV2>SPAN。
上面對(duì)需求的描述是一種文法,描述的是一組規(guī)則,現(xiàn)在要做的事實(shí)現(xiàn)一個(gè)規(guī)則解釋器來解釋上面的規(guī)則。首先要分析給出的文法,查找他們的相似點(diǎn),然后該清楚我們要先實(shí)現(xiàn)什么再實(shí)現(xiàn)什么,基本上問題就能解決了。

收獲與總結(jié)

一些描述性語句,幾次功能的提取抽象,形成了一套語法法則,這就是解釋器模式要處理的事情。是否能應(yīng)用解釋器模式的一條重要準(zhǔn)則是能否根據(jù)需求解析出一套完整的語法規(guī)則,不論該語法規(guī)則簡(jiǎn)單或是復(fù)雜都是必須的。

技巧型設(shè)計(jì)模式

技巧型設(shè)計(jì)模式是通過一些特定技巧來解決組件的某些方面的問題,這類技巧一般通過實(shí)踐經(jīng)驗(yàn)總結(jié)得到。這本書中總結(jié)了8種技巧型設(shè)計(jì)模式,分別是鏈模式,委托模式,數(shù)據(jù)訪問對(duì)象模式,節(jié)流模式,簡(jiǎn)單模板模式,惰性模式,參與者模式和等待者模式。有興趣的同學(xué)可以去買書來看哦,這里就不一一解釋了。

架構(gòu)型設(shè)計(jì)模式

架構(gòu)型設(shè)計(jì)模式是一類框架結(jié)構(gòu),通過提供一些子系統(tǒng),指定它們的職責(zé),并將它們條理清晰地組織在一起。現(xiàn)在流行的前端框架都用了這種類型的設(shè)計(jì)模式。本書總結(jié)了6種架構(gòu)型設(shè)計(jì)模式,分別是同步模塊模式,異步模塊模式,Widget模式,MVC模式,MVP模式和MVVM模式。

學(xué)習(xí)設(shè)計(jì)模式的學(xué)習(xí)對(duì)于我們來說任重而道遠(yuǎn),我們需要在實(shí)踐中不斷思考不斷總結(jié)。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/86616.html

相關(guān)文章

  • 你不知道的javascript(上卷)后感(二)

    摘要:詞法熟悉語法的開發(fā)者,箭頭函數(shù)在涉及綁定時(shí)的行為和普通函數(shù)的行為完全不一致。被忽略的作為的綁定對(duì)象傳入,使用的是默認(rèn)綁定規(guī)則。使用內(nèi)置遍歷數(shù)組返回迭代器函數(shù)普通對(duì)象不含有,無法使用,可以進(jìn)行改造,個(gè)人博客地址 this詞法 熟悉ES6語法的開發(fā)者,箭頭函數(shù)在涉及this綁定時(shí)的行為和普通函數(shù)的行為完全不一致。跟普通this綁定規(guī)則不一樣,它使用了當(dāng)前的詞法作用域覆蓋了this本來的值。...

    Ali_ 評(píng)論0 收藏0
  • 代碼之髓后感——如何高效的學(xué)習(xí)語言

    摘要:代碼之髓讀后感如何高效的學(xué)習(xí)語言技術(shù)讀后感王垠如何掌握程序語言代碼之髓這本書里提出了三種學(xué)習(xí)語言的方法如何高效的學(xué)習(xí)語言在比較中學(xué)習(xí)在歷史中學(xué)習(xí)在實(shí)踐中學(xué)習(xí)在比較中學(xué)習(xí)通過比較多種語言,總結(jié)出某種語言的獨(dú)有特點(diǎn),以及多種語言的共有特點(diǎn)。 title: 代碼之髓讀后感——如何高效的學(xué)習(xí)語言date: 2017-07-08 17:17:00categories: 技術(shù)tags: 讀后感 ...

    ivyzhang 評(píng)論0 收藏0
  • 你不知道的javascript(上卷)后感(一)

    摘要:遮蔽效應(yīng)作用域查找會(huì)在找到第一個(gè)匹配的標(biāo)識(shí)符時(shí)停止,不會(huì)繼續(xù)往上層作用域查找,這就會(huì)產(chǎn)生遮蔽效應(yīng)。會(huì)發(fā)現(xiàn)每一次輸出的都是為啥勒所有的回調(diào)函數(shù)回在循環(huán)結(jié)束后才會(huì)執(zhí)行事件循環(huán)。 三劍客 編譯,顧名思義,就是源代碼執(zhí)行前會(huì)經(jīng)歷的過程,分三個(gè)步驟, 分詞/詞法分析,將我們寫的代碼字符串分解成多個(gè)詞法單元 解析/語法分析,將詞法單元集合生成抽象語法樹(AST) 代碼生成,抽象語法樹(AST)轉(zhuǎn)...

    zhaofeihao 評(píng)論0 收藏0
  • Swiper插件后感

    摘要:今天,我無意中看到這樣一個(gè)東西,它叫做,這是一個(gè)開源免費(fèi)的適用于各種移動(dòng)端的觸摸滑動(dòng)插件。同時(shí)導(dǎo)航欄也是可以手動(dòng)滑動(dòng)的,當(dāng)用戶手動(dòng)滑動(dòng)導(dǎo)航欄,點(diǎn)擊某一個(gè)板塊時(shí),下面的內(nèi)容部分會(huì)隨即滑到相應(yīng)的內(nèi)容塊。 今天,我無意中看到這樣一個(gè)東西,它叫做Swiper,這是一個(gè)開源免費(fèi)的適用于各種移動(dòng)端的觸摸滑動(dòng)插件。看了一遍文檔,發(fā)現(xiàn)并不是很難,于是打算動(dòng)手自己寫一個(gè)Swiper官網(wǎng)上的稍復(fù)雜點(diǎn)的小d...

    CODING 評(píng)論0 收藏0
  • JavaScript語言精粹》內(nèi)容精選

    摘要:最近在讀語言精粹這本書,作者是是一名來自的資深架構(gòu)師,以創(chuàng)建和維護(hù)格式而為大家所熟知。三元運(yùn)算符有三個(gè)運(yùn)算數(shù)。嘗試從的成員屬性中取值將會(huì)導(dǎo)致異常。這個(gè)過程稱為委托。通過可取得它們所屬對(duì)象的上下文的方法稱為公共方法。 最近在讀《JavaScript語言精粹》這本書,作者是 Douglas Crockford;Douglas Crockford是一名來自 Yahoo!的資深JavaScri...

    SimonMa 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<