javaScript設計模式探究【1】

來源:互聯網
上載者:User

    這段時間,有空沒空的看了一下部落格園裡一個博友-湯姆大叔的深入理解javascript系列,也挺有收穫的,因為面試的臨近,感覺自己唯一的優勢可能就是javascript這一塊了,所以就加強加強,去圖書館借了一本javascript設計模式,挺薄的一本書,放在書架上挺不顯眼的,書架上各種外表光鮮亮麗的javascript書,都看的淩亂了,只是看到設計模式那四個大字,所以就借了來,剛開始只是那麼隨意的翻了那麼一兩章,就令我有一種豁然開朗之感,遠比書架上那些看似很牛逼的書好的多,現在看書的口味也開始有點叼了,書怎麼樣,翻一翻就能感受出來。後來一看是圖靈程式設計叢書,一時覺得外國人果然牛逼,那個翻譯也挺用功的,有些地方斟酌的很仔細,推薦一下《javascript設計模式》---Ross harmes  Dustin Diaz著

         現在也發現個問題,看的書如果不做一些筆記,過了一段時間,就沒什麼印象了,倒是有點習慣這種一邊看書,然後一邊總結髮博文,跟大家分享一下的做法了。其實要成為javascript大牛這條路挺崎嶇的,個人感覺比成為C++/Java這條路更困難,因為由於指令碼語言的定位,本身讓它去實現非常複雜的邏輯功能就不太現實,即使有,也不是很容易能接觸到的,另外由於它的靈活性,所以掌控它就不顯得那麼簡單了,總的來說需要經驗,還需要能夠給你一個平台。其他語言學起來難道不累嗎?也累吧,語言並不能代表什麼,要更多的往深層次的東西思考,例如設計模式。當然像我這樣的菜鳥,要走的路還有很長很長,加油,一步步來唄。總有爬到高出的時候。

        

View Code

//1.javascript裡最簡單,最常見的完成任務方式function startAnimation(){        ...}function stopAnimation(){        ...    }//2.使用prototypevar Anim = function(){        ...};Anim.prototype.start = function(){        ...}Anim.prototype.stop = function(){        ...    }//3.將類的定義封裝在一條聲明中var Anim = function(){    ...    }Anim.prototype = {    start: fucntion(){        ...        }    ,    stop: function(){        ...        }};//4.使用Function.prototype.method用於為類添加新方法Function.prototype.method = function(name,fn){    this.prototype[name] = fn ;};var Anim = function(){    ...};Anim.method('starrt',function(){    ...    });Anim.method('stop', function(){    ...});//5.鏈式調用Function.prototype.method = function(name,fn){    this.prototype[name] = fn ;    return this;};var Anim = function(){    ...};Anim.method('starrt',function(){    ...    }).method('stop', function(){    ...});

   不知道大家看完上面的5例代碼有什麼感受,反正我覺得挺驚豔的,可能文法什麼的我都學過,但是從沒有想過可以這麼用。尤其是第五種,記得不錯的話,JQuery應該大量的用到了這種鏈式調用的方式。

        1 介面

       在javascript中模仿介面的三種方法:注釋法,屬性檢查法和鴨式辨型法

        1.1 注釋法--用注釋法最簡單,但是效果最差,只是增加了一段注釋而已,對效能沒有影響,但是沒有錯誤檢查。

View Code

/*interface Composite{    function add(child);    function remove(child);    functiongetChild(index);}interface FormItem{    function save();}*/var CompositeForm = function(id, method,action){//iimplements Composite, FormItem    ...};//Implement the Composite interfaceCompositeForm.prototype.add = function(child){    ...    };CompositeForm.prototype.remove = function(child){    ...};CompositeForm.prototype.getChild = function(index){    ...};//Implement the FormItem interfaceCOmpositeForm.prototype.save = function(){    ...};

   1.2 屬性檢查模仿介面--所有類都明確地聲明自己實現了哪些介面,任何一個要求其啊承諾書屬於特定類型的函數都可以對這個屬性進行檢查,並在所需介面未在聲明之列時拋出一個錯誤,但是這種方法並未確保類真正實現了自稱實現的介面。需要一些額外工作,對效能略有影響。

View Code

/*interface Composite{    function add(child);    function remove(child);    functiongetChild(index);}interface FormItem{    function save();}*/var CompositeForm = function(id,method,action){    this.implementsInterfaces = ['Composite', 'FormItem'];    ...    };function addForm(formInstance){    if(!implements(formInstance,'Composite','FormItem')){        throw new Error("Object does not implements a required interface:");    }    }//The implememts function, which checks to see if an object declares that it//implements the required interfaces.function implements(object){    for(var i = 1; i<arguments.length;i++){        var interfaceName = arguments[i];        var interfaceFound = false;        for(var j =0;j<object.implementsInterfaces.length;j++){            if(object.implementsInterfaces[j] == interfaceName){                interfaceFound = true;                break;            }            }        if(!interfaceFound){            return false;        }    }        return true;}

   1.3 鴨式辨型模仿介面--類是否聲明自己支援哪些介面並不重要,只要它具有這些介面中的方法就行。定義:如果對象具有與介面定義的方法同名的所有方法,那麼就可以認定它實現了這個介面。

View Code

//Interfacesvar Composite = new Interface('Composite',['add','remove','getChild']);var FormItem = new interface('FormItem',['save']);//CompositeForm classvar CompositeForm = function(id, method, action){    ...    };function addForm(formInstance){    ensureImplements(formInstance, Composite, FormItem);    }//ensureImplements函數至少需要兩個參數,第一個參數是想要檢查的對象,其餘參數是據以對那個對象進行檢查的介面。

      1.4 具體實現方法---綜合第一種和第三種,用注釋聲明類支援的介面,提高代碼的可重用性及文檔的完整性。我們還用輔助類Interface及其類方法Interface.ensureImplements來對對象實現的方法進行顯式檢查。

View Code

//Interfacesvar Composite = new Interface('Composite',['add','remove','getChild']);var FormItem = new interface('FormItem',['save']);//CompositeForm classvar CompositeForm = function(id, method, action){    ...    };function addForm(formInstance){    ensureImplements(formInstance, Composite, FormItem);    }var interface = function(name,methods){    if(Arguments.length != 2){        throw new Error("Interface constructor called with:"+Arguments.length+"arguments, but expected exactly 2.");    }    this.name = name;    this.methods = [];    for(var i =0,len = methods.length;i<len;i++){        if(typeof methods[i] != 'string'){                throw new Error("Interface constructor expects method names to be passed in as a string.");        }            this.methods.push(methods[i]);    }};interface.ensureImplements = function(Object){    if(Arguments.length<2){        throw new Error("Function Interface.ensureImplements called with"+Arguments.length+"arguments,but expected at least 2.");        }        for(var i =1,len = Arguments.length;i<len;i++){        var interface = Arguments[i];        if(interface.constructor != Interface){            throw new Error("Function interface.ensureImplements expects arguments two and above to be instances of Interface.");            }            for(var j = 0,methodsLen = interface.methods.length;j<methodsLen;j++){            var method = interface.methods[j];            if(!Object[method]||typeof Object[method]!=='function'){                throw new Error("Function Interface.ensureImplements:object does not implement the"+interface.name+"inerface.Method"+method+                "was not found.");                }            }    }};

  1.5 總結是否需要使用介面

        仁者見仁智者見智,對於一些小型的,不太費事的項目,就沒必要使用了。具體實現的時候,還可以簡化。使用公用的Interface.js檔案,剔除所有針對構造器的顯式檢查,以Interface.ensureImplements取代原來的構造器檢查。

     2 封裝和資訊隱藏

      javascript中建立對象的基本模式有3種。門戶大開型,使用底線來表示私人方法和屬性,使用閉包來建立真正的私人成員。

  2.1 門戶大開型---所有的屬性和方法都是公開的,可訪問的(就不舉例了)

       2.2 用命名規範區別私人成員---本質上來說這種模式與門戶大開型對象建立模式如出一轍,只不過在一些方法和屬性的名稱前加上了底線以示其私用性而已。

       //this._menber = member;

     //_method = function(){}               但是這樣外部其實還是可以訪問的。

     2.3 範圍、嵌套函數和閉包

     在javascript中只有函數具有範圍。閉包的好處就是可以實現在函數外部調用內部的變數。返回一個內嵌函數是建立閉包的最常用的手段。

View Code

function foo(){    var a = 10;    function bar(){        a * = 2;        return a;    }    return bar;    }var baz = foo();      baz(); //return 20baz(); //return 40baz(); //return 80var blat = foo();blat();          //return 20   because a new copy of a is being used

     上面這段代碼其實涉及到共用變數的問題,var baz = foo() 聲明一個函數bar的引用。使用baz的時候共用變數a,具體的可以看深入理解JavaScript系列(10):JavaScript核心(晉級高手必讀篇)裡面有涉及到,講的挺詳細的。

     2.4 總結封裝利弊:

           封裝保護了內部資料的完整性,通過將資料的訪問途徑限制為取值器和賦值器這兩個方法可以獲得對取值和賦值的完全控制,可以減少其它函數所需的錯誤檢查代碼的數量。 對   象重構因此變得輕鬆。通過只公開在那些介面中規定的方法,可以弱化模組間的耦合。

           封裝導致了複雜的範圍鏈。學習起來挺困難的,新手容易迷糊。

      3 繼承--在javascript中繼承是非常複雜的,比其他任何物件導向語言中的繼承都要複雜...下次再總結吧,我感覺就繼承,我能寫一篇博文了。沒事的話,明天繼續

       以上全部都屬個人原創,請大家轉載的時候附上原創連結: http://www.cnblogs.com/tonylp

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.