真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

JavaScript閉包以及幾種設(shè)計(jì)模式的詳細(xì)介紹

這篇文章主要介紹“JavaScript閉包以及幾種設(shè)計(jì)模式的詳細(xì)介紹”,在日常操作中,相信很多人在JavaScript閉包以及幾種設(shè)計(jì)模式的詳細(xì)介紹問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”JavaScript閉包以及幾種設(shè)計(jì)模式的詳細(xì)介紹”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

創(chuàng)新互聯(lián)公司主要從事成都網(wǎng)站設(shè)計(jì)、網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)呼中,十多年網(wǎng)站建設(shè)經(jīng)驗(yàn),價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):18980820575

JavaScript閉包

1.閉包最常用的方式就是返回一個內(nèi)聯(lián)函數(shù)(何為內(nèi)聯(lián)函數(shù)?就是在函數(shù)內(nèi)部聲明的函數(shù));

2.在JavaScript中有作用域和執(zhí)行環(huán)境的問題,在函數(shù)內(nèi)部的變量在函數(shù)外部是無法訪問的,在函數(shù)內(nèi)部卻可以得到全局變量。由于種種原因,我們有時候需要得到函數(shù)內(nèi)部的變量,可是用常規(guī)方法是得不到的,這時我們就可以創(chuàng)建一個閉包,用來在外部訪問這個變量。

3.閉包的用途 主要就是上一點(diǎn)提到的讀取函數(shù)內(nèi)部變量,還有一個作用就是可以使這些變量一直保存在內(nèi)存中。

4.使用閉包要注意,由于變量被保存在內(nèi)存中,所以會對內(nèi)存造成消耗,所以不能濫用閉包。解決方法是 在退出函數(shù)之前,將不使用的局部變量全部刪除。

***還是上一套閉包的代碼吧,這樣更直觀。

function f(){   var n = 999;   function f1(){     alert(n+=1);    }   return f1;  }  var result = f();  result(); // 1000  result(); // 1001  result(); // 1002

封裝:通過將一個方法或者屬性聲明為私用的,可以讓對象的實(shí)現(xiàn)細(xì)節(jié)對其他對象保密以降低對象之間的耦合程度,可以保持?jǐn)?shù)據(jù)的完整性并對其修改方式加以約束,這樣可以是代碼更可靠,更易于調(diào)試。封裝是面向?qū)ο蟮脑O(shè)計(jì)的基石。

盡管JavaScript是一門面向?qū)ο蟮恼Z言,可它并不具備將成員聲明為公用或私用的任何內(nèi)部機(jī)制,所以我們只能自己想辦法實(shí)現(xiàn)這種特性。下面還是通過一套完整的代碼去分析,介紹什么是私有屬性和方法,什么是特權(quán)屬性和方法,什么是公有屬性和方法,什么是公有靜態(tài)屬性和方法。

私有屬性和方法:函數(shù)有作用域,在函數(shù)內(nèi)用var 關(guān)鍵字聲明的變量在外部無法訪問,私有屬性和方法本質(zhì)就是你希望在對象外部無法訪問的變量。

特權(quán)屬性和方法:創(chuàng)建屬性和方法時使用的this關(guān)鍵字,因?yàn)檫@些方法定義在構(gòu)造器的作用域中,所以它們可以訪問到私有屬性和方法;只有那些需要直接訪問私有成員的方法才應(yīng)該被設(shè)計(jì)為特權(quán)方法。

共有屬性和方法:直接鏈在prototype上的屬性和方法,不可以訪問構(gòu)造器內(nèi)的私有成員,可以訪問特權(quán)成員,子類會繼承所有的共有方法。

共有靜態(tài)屬性和方法:***的理解方式就是把它想象成一個命名空間,實(shí)際上相當(dāng)于把構(gòu)造器作為命名空間來使用。

 /* -- 封裝 -- */  var _packaging = function(){      //私有屬性和方法      var name = 'Darren';      var method1 = function(){         //...      }      //特權(quán)屬性和方法      this.title = 'JavaScript Design Patterns' ;      this.getName = function(){         return name;      }   }   //共有靜態(tài)屬性和方法   _packaging._name = 'Darren code';   _packaging.alertName = function(){      alert(_packaging._name);   }  //共有屬性和方法  _packaging.prototype = {      init:function(){         //...      }   }

繼承:繼承本身就是一個抽象的話題,在JavaScript中繼承更是一個復(fù)雜的話題,因?yàn)镴avaScript想要實(shí)現(xiàn)繼承有兩種實(shí)現(xiàn)方式,分別是類式繼承和原型式繼承,每種實(shí)現(xiàn)的方式都需要采取不少措施,下面本人通過分析例子的方式講解JavaScript中這個很重要的話題。

 /* -- 類式繼承 -- */  //先聲明一個超類   function Person(name){   this.name = name;   }   //給這個超類的原型對象上添加方法 getName    Person.prototype.getName = function(){      return this.name;   }   //實(shí)例化這個超類   var a = new Person('Darren1')   alert(a.getName());   //再聲明類   function Programmer(name,sex){      //這個類中要調(diào)用超類Person的構(gòu)造函數(shù),并將參數(shù)name傳給它      Person.call(this,name);      this.sex = sex;   }   //這個子類的原型對象等于超類的實(shí)例   Programmer.prototype = new Person();   //因?yàn)樽宇惖脑蛯ο蟮扔诔惖膶?shí)例,所以prototype.constructor這個方法也等于超類構(gòu)造函數(shù),你可以自己測試一下,如果沒這一步,alert(Programmer.prototype.constructor),這個是Person超類的引用,所以要從新賦值為自己本身   Programmer.prototype.constructor = Programmer;   //子類本身添加了getSex 方法   Programmer.prototype.getSex = function(){      return this.sex;   }   //實(shí)例化這個子類   var _m = new Programmer('Darren2','male');   //自身的方法   alert(_m.getSex());   //繼承超類的方法  alert(_m.getName());

代碼都不難,只要對 原型鏈有基礎(chǔ)就能理解。類式繼承模式是JavaScript繼承主要的模式,幾乎所有用面向?qū)ο蠓绞骄帉懙腏avaScript代碼中都用到了這種繼承,又因?yàn)樵诟鞣N流行語言中只有JavaScript使用原型式繼承,因此***還是使用類式繼承??墒且煜avaScript語言,原型繼承也是我們必須所了解的,至于在項(xiàng)目中是否使用就得看個人編碼風(fēng)格了。

 /* -- 原型式繼承 -- */  //clone()函數(shù)用來創(chuàng)建新的類Person對象   var clone = function(obj){      var _f = function(){};      //這句是原型式繼承最核心的地方,函數(shù)的原型對象為對象字面量      _f.prototype = obj;       return new _f;   }   //先聲明一個對象字面量   var Person = {      name:'Darren',      getName:function(){         return this.name;      }   }   //不需要定義一個Person的子類,只要執(zhí)行一次克隆即可   var Programmer = clone(Person);   //可以直接獲得Person提供的默認(rèn)值,也可以添加或者修改屬性和方法   alert(Programmer.getName())   Programmer.name = 'Darren2'  alert(Programmer.getName())      //聲明子類,執(zhí)行一次克隆即可   var Someone = clone(Programmer);

JavaScript設(shè)計(jì)模式的作用 - 提高代碼的重用性,可讀性,使代碼更容易的維護(hù)和擴(kuò)展。

1.單體模式,工廠模式,橋梁模式個人認(rèn)為這個一個優(yōu)秀前端必須掌握的模式,對抽象編程和接口編程都非常有好處。

2.裝飾者模式和組合模式有很多相似的地方,它們都與所包裝的對象實(shí)現(xiàn)同樣的接口并且會把任何方法的調(diào)用傳遞給這些對象。裝飾者模式和組合模式是本人描述的較吃力的兩個模式,我個人其實(shí)也沒用過,所以查了很多相關(guān)資料和文檔,請大家海涵。

3.門面模式是個非常有意思的模式,幾乎所有的JavaScript庫都會用到這個模式,假如你有逆向思維或者逆向編程的經(jīng)驗(yàn),你會更容易理解這個模式(聽起來有挑戰(zhàn),其實(shí)一接觸你就知道這是個很簡單的模式);還有配置器模式得和門面模式一塊拿來說,這個模式對現(xiàn)有接口進(jìn)行包裝,合理運(yùn)用可以很多程度上提高開發(fā)效率。這兩個模式有相似的地方,所以一塊理解的話相信都會很快上手的。

4.享元模式是一種以優(yōu)化為目的的模式。

5.代理模式主要用于控制對象的訪問,包括推遲對其創(chuàng)建需要耗用大量計(jì)算資源的類得實(shí)例化。

6.觀察者模式用于對對象的狀態(tài)進(jìn)行觀察,并且當(dāng)它發(fā)生變化時能得到通知的方法。用于讓對象對事件進(jìn)行監(jiān)聽以便對其作出響應(yīng)。觀察者模式也被稱為“訂閱者模式”。

7.命令模式是對方法調(diào)用進(jìn)行封裝的方式,用命名模式可以對方法調(diào)用進(jìn)行參數(shù)化和傳遞,然后在需要的時候再加以執(zhí)行。

8.職責(zé)鏈模式用來消除請求的發(fā)送者和接收者之間的耦合。

JavaScript設(shè)計(jì)模式都有哪些?

單體(Singleton)模式:絕對是JavaScript中最基本最有用的模式。

單體在JavaScript的有多種用途,它用來劃分命名空間??梢詼p少網(wǎng)頁中全局變量的數(shù)量(在網(wǎng)頁中使用全局變量有風(fēng)險);可以在多人開發(fā)時避免代碼的沖突(使用合理的命名空間)等等。

在中小型項(xiàng)目或者功能中,單體可以用作命名空間把自己的代碼組織在一個全局變量名下;在稍大或者復(fù)雜的功能中,單體可以用來把相關(guān)代碼組織在一起以便日后好維護(hù)。

使用單體的方法就是用一個命名空間包含自己的所有代碼的全局對象,示例:

var functionGroup = {   name:'Darren',   method1:function(){   //code   },   init:function(){   //code   }   }

或者

var functionGroup  = new function myGroup(){   this.name = 'Darren';   this.getName = function(){   return this.name   }   this.method1 = function(){}   ...   }

工廠(Factory)模式:提供一個創(chuàng)建一系列相關(guān)或相互依賴對象的接口,而無需指定他們具體的類。

工廠就是把成員對象的創(chuàng)建工作轉(zhuǎn)交給一個外部對象,好處在于消除對象之間的耦合(何為耦合?就是相互影響)。通過使用工廠方法而不是new關(guān)鍵字及具體類,可以把所有實(shí)例化的代碼都集中在一個位置,有助于創(chuàng)建模塊化的代碼,這才是工廠模式的目的和優(yōu)勢。

舉個例子:你有一個大的功能要做,其中有一部分是要考慮擴(kuò)展性的,那么這部分代碼就可以考慮抽象出來,當(dāng)做一個全新的對象做處理。好處就是將來擴(kuò)展的時候容易維護(hù) - 只需要操作這個對象內(nèi)部方法和屬性,達(dá)到了動態(tài)實(shí)現(xiàn)的目的。非常有名的一個示例 - XHR工廠:

var XMLHttpFactory = function(){};//這是一個簡單工廠模式   XMLHttpFactory.createXMLHttp = function(){   var XMLHttp = null;   if (window.XMLHttpRequest){   XMLHttp = new XMLHttpRequest()   }else if (window.ActiveXObject){   XMLHttp = new ActiveXObject("Microsoft.XMLHTTP")   }   return XMLHttp;   }   //XMLHttpFactory.createXMLHttp()這個方法根據(jù)當(dāng)前環(huán)境的具體情況返回一個XHR對象。   var AjaxHander = function(){   var XMLHttp = XMLHttpFactory.createXMLHttp();   ...   }

工廠模式又區(qū)分簡單工廠模式和抽象工廠模式,上面介紹的是簡單工廠模式,這種模式用的更多也更簡單易用。抽象工廠模式的使用方法就是 - 先設(shè)計(jì)一個抽象類,這個類不能被實(shí)例化,只能用來派生子類,***通過對子類的擴(kuò)展實(shí)現(xiàn)工廠方法。 示例:

var XMLHttpFactory = function(){};      //這是一個抽象工廠模式   XMLHttpFactory.prototype = {      //如果真的要調(diào)用這個方法會拋出一個錯誤,它不能被實(shí)例化,只能用來派生子類      createFactory:function(){         throw new Error('This is an abstract class');      }   }  //派生子類,文章開始處有基礎(chǔ)介紹那有講解繼承的模式,不明白可以去參考原理   var XHRHandler = function(){      XMLHttpFactory.call(this);   };  XHRHandler.prototype = new XMLHttpFactory();   XHRHandler.prototype.constructor = XHRHandler;   //重新定義createFactory 方法   XHRHandler.prototype.createFactory = function(){      var XMLHttp = null;      if (window.XMLHttpRequest){         XMLHttp = new XMLHttpRequest()      }else if (window.ActiveXObject){         XMLHttp = new ActiveXObject("Microsoft.XMLHTTP")      }      return XMLHttp;   }

橋接(bridge)模式:在實(shí)現(xiàn)API的時候,橋梁模式灰常有用。在所有模式中,這種模式最容易立即付諸實(shí)施。

橋梁模式可以用來弱化它與使用它的類和對象之間的耦合,就是將抽象與其實(shí)現(xiàn)隔離開來,以便二者獨(dú)立變化;這種模式對于JavaScript中常見的時間驅(qū)動的編程有很大益處,橋梁模式最常見和實(shí)際的應(yīng)用場合之一是時間監(jiān)聽器回調(diào)函數(shù)。先分析一個不好的示例:

element.onclick = function(){      new setLogFunc();   };

為什么說這個示例不好,因?yàn)閺倪@段代碼中無法看出那個LogFunc方法要顯示在什么地方,它有什么可配置的選項(xiàng)以及應(yīng)該怎么去修改它。換一種說法就是,橋梁模式的要訣就是讓接口“可橋梁”,實(shí)際上也就是可配置。把頁面中一個個功能都想象成模塊,接口可以使得模塊之間的耦合降低。

掌握橋梁模式的正確使用收益的不只是你,還有那些負(fù)責(zé)維護(hù)你代碼的人。把抽象于其實(shí)現(xiàn)隔離開,可獨(dú)立地管理軟件的各個部分,bug也因此更容易查找。

橋梁模式目的就是讓API更加健壯,提高組件的模塊化程度,促成更簡潔的實(shí)現(xiàn),并提高抽象的靈活性。一個好的示例:

element.onclick = function(){//API可控制性提高了,使得這個API更加健壯      new someFunction(element,param,callback);  }

注:橋梁模式還可以用于連接公開的API代碼和私有的實(shí)現(xiàn)代碼,還可以把多個類連接在一起。在文章封裝介紹的部分提到過特權(quán)方法,也是橋梁模式的一種特例。《JS設(shè)計(jì)模式》上找的示例,加深大家對這個模式的理解:

 //錯誤的方式   //這個API根據(jù)事件監(jiān)聽器回調(diào)函數(shù)的工作機(jī)制,事件對象被作為參數(shù)傳遞給這個函數(shù)。本例中并沒有使用這個參數(shù),而只是從this對象獲取ID。   addEvent(element,'click',getBeerById);   function(e){      var id = this.id;      asyncRequest('GET','beer.url?id=' + id,function(resp){         //Callback response         console.log('Requested Beer: ' + resp.responseText);      });   }      //好的方式   //從邏輯上分析,把id傳給getBeerById函數(shù)式合情理的,且回應(yīng)結(jié)果總是通過一個毀掉函數(shù)返回。這么理解,我們現(xiàn)在做的是針對接口而不是實(shí)現(xiàn)進(jìn)行編程,用橋梁模式把抽象隔離開來。   function getBeerById(id,callback){      asyncRequest('GET','beer.url?id=' + id,function(resp){         callback(resp.responseText)      });   }   addEvent(element,'click',getBeerByIdBridge);   function getBeerByIdBridge(e){      getBeerById(this.id,function(beer){         console.log('Requested Beer: ' + beer);      });   } 

裝飾者(Decorator)模式:這個模式就是為對象增加功能(或方法)。

動態(tài)地給一個對象添加一些額外的職責(zé)。就擴(kuò)展功能而言,它比生成子類方式更為靈活。

裝飾者模式和組合模式有很多共同點(diǎn),它們都與所包裝的對象實(shí)現(xiàn)統(tǒng)一的接口并且會把任何方法條用傳遞給這些對象??墒墙M合模式用于把眾多子對象組織為一個整體,而裝飾者模式用于在不修改現(xiàn)有對象或從派生子類的前提下為其添加方法。

裝飾者的運(yùn)作過程是透明的,這就是說你可以用它包裝其他對象,然后繼續(xù)按之前使用那么對象的方法來使用,從下面的例子中就可以看出。還是從代碼中理解吧:

//創(chuàng)建一個命名空間為myText.Decorations   var myText= {};   myText.Decorations={};   myText.Core=function(myString){      this.show = function(){return myString;}   }   //***次裝飾   myText.Decorations.addQuestuibMark =function(myString){      this.show = function(){return myString.show()+'?';};   }   //第二次裝飾   myText.Decorations.makeItalic = function(myString){      this.show = function(){return '
  • '+myString.show()+'
  • '};   }   //得到myText.Core的實(shí)例   var theString = new myText.Core('this is a sample test String');   alert(theString.show());//output 'this is a sample test String'   theString = new myText.Decorations.addQuestuibMark(theString);   alert(theString.show());//output 'this is a sample test String?'   theString = new myText.Decorations.makeItalic (theString);   alert(theString.show());//output '
  • this is a sample test String
  • '

    從這個示例中可以看出,這一切都可以不用事先知道組件對象的接口,甚至可以動態(tài)的實(shí)現(xiàn),在為現(xiàn)有對象增添特性這方面,裝飾者模式有極大的靈活性。

    如果需要為類增加特性或者方法,而從該類派生子類的解決辦法并不實(shí)際的話,就應(yīng)該使用裝飾者模式。派生子類之所以會不實(shí)際最常見的原因是需要添加的特性或方法的數(shù)量要求使用大量子類。

    組合(Composite)模式:將對象組合成樹形結(jié)構(gòu)以表示“部分-整體”的層次結(jié)構(gòu)。它使得客戶對單個對象和復(fù)合對象的使用具有一致性。

    組合模式是一種專為創(chuàng)建Web上的動態(tài)用戶界面而量身定制的模式。使用這種模式,可以用一條命令在多個對象上激發(fā)復(fù)雜的或遞歸的行為。組合模式擅長于對大批對象進(jìn)行操作。

    組合模式的好處:1.程序員可以用同樣的方法處理對象的集合與其中的特定子對象;2.它可以用來把一批子對象組織成樹形結(jié)構(gòu),并且使整棵樹都可被便利。

    組合模式適用范圍:1.存在一批組織成某處層次體系的對象(具體結(jié)構(gòu)可能在開發(fā)期間無法知道);2.希望對這批對象或其中的一部分對象實(shí)話一個操作。

    其實(shí)組合模式就是將一系列相似或相近的對象組合在一個大的對象,由這個大對象提供一些常用的接口來對這些小對象進(jìn)行操作,代碼可重用,對外操作簡單。例如:對form內(nèi)的元素,不考慮頁面設(shè)計(jì)的情況下,一般就剩下input了,對于這些input都有name和value的屬性,因此可以將這些input元素作為form對象的成員組合起來,form對象提供對外的接口,便可以實(shí)現(xiàn)一些簡單的操作,比如設(shè)置某個input的value,添加/刪除某個input等等。

    這種模式描述起來比較吃力,我從《JS設(shè)計(jì)模式》上找個一個實(shí)例,大家還是看代碼吧:先創(chuàng)建組合對象類

    // DynamicGallery Class   var DynamicGallery = function (id) { // 實(shí)現(xiàn)Composite,GalleryItem組合對象類       this.children = [];      this.element = document.createElement('div');      this.element.id = id;      this.element.className = 'dynamic-gallery';   }   DynamicGallery.prototype = {      // 實(shí)現(xiàn)Composite組合對象接口       add: function (child) {         this.children.push(child);         this.element.appendChild(child.getElement());      },      remove: function (child) {         for (var node, i = 0; node = this.getChild(i); i++) {            if (node == child) {               this.children.splice(i, 1);               break;            }         }         this.element.removeChild(child.getElement());      },      getChild: function (i) {         return this.children[i];      },      // 實(shí)現(xiàn)DynamicGallery組合對象接口       hide: function () {         for (var node, i = 0; node = this.getChild(i); i++) {            node.hide();         }         this.element.style.display = 'none';     },      show: function () {         this.element.style.display = 'block';         for (var node, i = 0; node = getChild(i); i++) {            node.show();         }      },      // 幫助方法       getElement: function () {         return this.element;      }   }

    再創(chuàng)建葉對象類

    var GalleryImage = function (src) { // 實(shí)現(xiàn)Composite和GalleryItem組合對象中所定義的方法       this.element = document.createElement('img');      this.element.className = 'gallery-image';      this.element.src = src;   }   GalleryImage.prototype = {      // 實(shí)現(xiàn)Composite接口       // 這些是葉結(jié)點(diǎn),所以我們不用實(shí)現(xiàn)這些方法,我們只需要定義即可       add: function () { },      remove: function () { },      getChild: function () { },      // 實(shí)現(xiàn)GalleryItem接口       hide: function () {         this.element.style.display = 'none';      },      show: function () {         this.element.style.display = '';      },     // 幫助方法       getElement: function () {        return this.element;      }   }

    現(xiàn)在我們可以使用這兩個類來管理圖片:

    var topGallery = new DynamicGallery('top-gallery');    topGallery.add(new GalleryImage('/img/image-1.jpg'));    topGallery.add(new GalleryImage('/img/image-2.jpg'));    topGallery.add(new GalleryImage('/img/image-3.jpg'));    var vacationPhotos = new DyamicGallery('vacation-photos');    for(var i = 0, i < 30; i++){    vacationPhotos.add(new GalleryImage('/img/vac/image-' + i + '.jpg'));    }    topGallery.add(vacationPhotos);    topGallery.show();    vacationPhotos.hide();

    門面(facade)模式:門面模式是幾乎所有JavaScript庫的核心原則

    子系統(tǒng)中的一組接口提供一個一致的界面,門面模式定義了一個高層接口,這個接口使得這一子系統(tǒng)更加容易使用,簡單的說這是一種組織性的模式,它可以用來修改類和對象的接口,使其更便于使用。

    門面模式的兩個作用:1.簡化類的接口;2.消除類與使用它的客戶代碼之間的耦合。

    門面模式的使用目的就是圖方面。

    想象一下計(jì)算機(jī)桌面上的那些快捷方式圖標(biāo),它們就是在扮演一個把用戶引導(dǎo)至某個地方的接口的角色,每次操作都是間接的執(zhí)行一些幕后的命令。

    你在看這篇的博客的時候我就假設(shè)你已經(jīng)有JavaScript的使用經(jīng)驗(yàn)了,那么你一定寫過或者看過這樣的代碼:

    var addEvent = function(el,type,fn){      if(window.addEventListener){         el.addEventListener(type,fn);      }else if(window.attachEvent){         el.attachEvent('on'+type,fn);      }else{         el['on'+type] = fn;      }   }

    這個就是一個JavaScript中常見的事件監(jiān)聽器函數(shù),這個函數(shù)就是一個基本的門面,有了它,就有了為DOM節(jié)點(diǎn)添加事件監(jiān)聽器的簡便方法。

    現(xiàn)在要說門面模式的精華部分了,為什么說JavaScript庫幾乎都會用這種模式類。假如現(xiàn)在要設(shè)計(jì)一個庫,那么***把其中所有的工具元素放在一起,這樣更好用,訪問起來更簡便。看代碼:

    //_model.util是一個命名空間   _myModel.util.Event = {      getEvent:function(e){         return e|| window.event;      },      getTarget:function(e){         return e.target||e.srcElement;      },      preventDefault:function(e){         if(e.preventDefault){            e.preventDefault();         }else{            e.returnValue = false;         }      }   };   //事件工具大概就是這么一個套路,然后結(jié)合addEvent函數(shù)使用   addEvent(document.getElementsByTagName('body')[0],'click',function(e){      alert(_myModel.util.Event.getTarget(e));   });

    個人認(rèn)為,在處理游覽器差異問題時***的解決辦法就是把這些差異抽取的門面方法中,這樣可以提供一個更一致的接口,addEvent函數(shù)就是一個例子。

    適配置器(Adapter)模式:將一個類的接口轉(zhuǎn)換成客戶希望的另外一個接口。適配器模式使得原本由于接口不兼容而不能一起工作的那些類可以一起工作,使用這種模式的對象又叫包裝器,因?yàn)樗麄兪窃谟靡粋€新的接口包裝另一個對象。

    從表面上看,它和門面模式有點(diǎn)相似,差別在于它們?nèi)绾胃淖兘涌?,門面模式展現(xiàn)的是一個簡化的接口,它并不提供額外的選擇,而適配器模式則要把一個接口轉(zhuǎn)換為另一個接口,它并不會濾除某些能力,也不會簡化接口。先來一個簡單的示例看看:

    //假如有一個3個字符串參數(shù)的函數(shù),但是現(xiàn)在擁有的卻是一個包含三個字符串元素的對象,那么就可以用一個配置器來銜接二者   var clientObject = {      str1:'bat',      str2:'foo',      str3:'baz'  }   function interfaceMethod(str1,str2,str3){   alert(str1)   }   //配置器函數(shù)   function adapterMethod(o){      interfaceMethod(o.str1, o.str2, o.str3);   }   adapterMethod(clientObject)   //adapterMethod函數(shù)的作為就在于對interfaceMethod函數(shù)進(jìn)行包裝,并把傳遞給它的參數(shù)轉(zhuǎn)換為后者需要的形式。

    適配器模式的工作機(jī)制是:用一個新的接口對現(xiàn)有類得接口進(jìn)行包裝。

    示例:適配兩個庫。下面的例子要實(shí)現(xiàn)的是從Prototype庫的$函數(shù)到Y(jié)UI的get方法的轉(zhuǎn)換。

    //先看它們在接口方面的差別   //Prototype $ function    function $(){      var elements = new Array();      for(var i=0;i

    享元(Flyweight)模式:運(yùn)用共享技術(shù)有效地支持大量細(xì)粒度的對象。

    享元模式可以避免大量非常相似類的開銷。在程序設(shè)計(jì)中有時需要生成大量細(xì)粒度的類實(shí)例來表示數(shù)據(jù)。如果發(fā)現(xiàn)這些實(shí)例除了幾個參數(shù)外基本傷都是相同的,有時就能夠受大幅度第減少需要實(shí)例化的類的數(shù)量。如果能把這些參數(shù)移到類實(shí)例外面,在方法調(diào)用時將他們傳遞進(jìn)來,就可以通過共享大幅度地減少單個實(shí)例的數(shù)目。

    從實(shí)際出發(fā)說說自己的理解吧。

    組成部分

    “享元”:抽離出來的外部操作和數(shù)據(jù);

    “工廠”:創(chuàng)造對象的工廠;

    “存儲器”:存儲實(shí)例對象的對象或數(shù)組,供“享元”來統(tǒng)一控制和管理。

    應(yīng)用場景

    1. 頁面存在大量資源密集型對象;

    2. 這些對象具備一定的共性,可以抽離出公用的操作和數(shù)據(jù)

    關(guān)鍵

    1. 合理劃分內(nèi)部和外部數(shù)據(jù)。

    既要保持每個對象的模塊性、保證享元的獨(dú)立、可維護(hù),又要盡可能多的抽離外部數(shù)據(jù)。

    2. 管理所有實(shí)例

    既然抽離出了外部數(shù)據(jù)和操作,那享元就必須可以訪問和控制實(shí)例對象。在JavaScript這種動態(tài)語言中,這個需求是很容易實(shí)現(xiàn)的:我們可以把工廠生產(chǎn)出的對象簡單的扔在一個數(shù)組中。為每個對象設(shè)計(jì)暴露給外部的方法,便于享元的控制。

    優(yōu)點(diǎn)

    1. 將能耗大的操作抽離成一個,在資源密集型系統(tǒng)中,可大大減少資源和內(nèi)存占用;

    2. 職責(zé)封裝,這些操作獨(dú)立修改和維護(hù);

    缺點(diǎn)

    1. 增加了實(shí)現(xiàn)復(fù)雜度。

    將原本由一個工廠方法實(shí)現(xiàn)的功能,修改為了一個享元+一個工廠+一個存儲器。

    2. 對象數(shù)量少的情況,可能會增大系統(tǒng)開銷。

    示例:

    //汽車登記示例   var Car = function(make,model,year,owner,tag,renewDate){   this.make=make;   this.model=model;   this.year=year;   this.owner=owner;   this.tag=tag;   this.renewDate=renewDate;   }   Car.prototype = {   getMake:function(){   return this.make;   },   getModel:function(){   return this.model;   },   getYear:function(){   return this.year;   },   transferOwner:function(owner,tag,renewDate){   this.owner=owner;   this.tag=tag;   this.renewDate=renewDate;   },   renewRegistration:function(renewDate){   this.renewDate=renewDate;   }   }   //數(shù)據(jù)量小到?jīng)]多大的影響,數(shù)據(jù)量大的時候?qū)τ?jì)算機(jī)內(nèi)存會產(chǎn)生壓力,下面介紹享元模式優(yōu)化后   //包含核心數(shù)據(jù)的Car類   var Car=function(make,model,year){   this.make=make;   this.model=model;   this.year=year;   }   Car.prototype={   getMake:function(){   return this.make;   },   getModel:function(){   return this.model;   },   getYear:function(){   return this.year;   }   }   //中間對象,用來實(shí)例化Car類   var CarFactory=(function(){   var createdCars = {};   return {   createCar:function(make,model,year){   var car=createdCars[make+"-"+model+"-"+year];   return car ? car : createdCars[make + '-' + model + '-' + year] =(new Car(make,model,year));   }   }   })();   //數(shù)據(jù)工廠,用來處理Car的實(shí)例化和整合附加數(shù)據(jù)   var CarRecordManager = (function() {   var carRecordDatabase = {};   return {   addCarRecord:function(make,model,year,owner,tag,renewDate){   var car = CarFactory.createCar(make, model, year);   carRecordDatabase[tag]={   owner:owner,   tag:tag,   renewDate:renewDate,   car:car   }   },   transferOwnership:function(tag, newOwner, newTag, newRenewDate){   var record=carRecordDatabase[tag];   record.owner = newOwner;   record.tag = newTag;   record.renewDate = newRenewDate;   },   renewRegistration:function(tag,newRenewDate){   carRecordDatabase[tag].renewDate=newRenewDate;   },   getCarInfo:function(tag){   return carRecordDatabase[tag];   }   }   })();

    代理(Proxy)模式:此模式最基本的形式是對訪問進(jìn)行控制。代理對象和另一個對象(本體)實(shí)現(xiàn)的是同樣的接口,可是實(shí)際上工作還是本體在做,它才是負(fù)責(zé)執(zhí)行所分派的任務(wù)的那個對象或類,代理對象不會在另以對象的基礎(chǔ)上修改任何方法,也不會簡化那個對象的接口。

    舉一個具體的情況:如果那個對象在某個遠(yuǎn)端服務(wù)器上,直接操作這個對象因?yàn)榫W(wǎng)絡(luò)速度原因可能比較慢,那我們可以先用Proxy來代替那個對象。

    總之對于開銷較大的對象,只有在使用它時才創(chuàng)建,這個原則可以為我們節(jié)省很多內(nèi)存?!禞S設(shè)計(jì)模式》上的圖書館示例:

    var Publication = new Interface('Publication', ['getIsbn', 'setIsbn', 'getTitle', 'setTitle', 'getAuthor', 'setAuthor', 'display']);   var Book = function(isbn, title, author) {       //...   }    // implements Publication   implements(Book,Publication);      /* Library interface. */  var Library = new Interface('Library', ['findBooks', 'checkoutBook', 'returnBook']);      /* PublicLibrary class. */  var PublicLibrary = function(books) {       //...   };   // implements Library   implements(PublicLibrary,Library);       PublicLibrary.prototype = {       findBooks: function(searchString) {          //...       },       checkoutBook: function(book) {           //...       },       returnBook: function(book) {           //...       }   };      /* PublicLibraryProxy class, a useless proxy. */  var PublicLibraryProxy = function(catalog) {        this.library = new PublicLibrary(catalog);   };   // implements Library   implements(PublicLibraryProxy,Library);      PublicLibraryProxy.prototype = {       findBooks: function(searchString) {           return this.library.findBooks(searchString);       },       checkoutBook: function(book) {           return this.library.checkoutBook(book);       },       returnBook: function(book) {           return this.library.returnBook(book);       }   };

    觀察者(Observer)模式:定義對象間的一種一對多的依賴關(guān)系,以便當(dāng)一個對象的狀態(tài)發(fā)生改變時,所有依賴于它的對象都得到通知并自動刷新。

    觀察者模式中存在兩個角色,觀察者和被觀察者。在DOM的編程環(huán)境中的高級事件模式中,事件監(jiān)聽器說到底就是一種內(nèi)置的觀察者。事件處理器(handler)和時間監(jiān)聽器(listener)并不是一回事,前者就是一種把事件傳給與其關(guān)聯(lián)的函數(shù)的手段,而在后者中,一個時間可以與幾個監(jiān)聽器關(guān)聯(lián),每個監(jiān)聽器都能獨(dú)立于其他監(jiān)聽器而改變。

    //使用時間監(jiān)聽器可以讓多個函數(shù)相應(yīng)一個事件   var fn1 = function(){      //code  }   var fn2 = function(){      //code   }    addEvent(element,'click',fn1);   addEvent(element,'click',fn2)   //而時間處理函數(shù)就辦不到   element.onclick = fn1;   element.onclick = fn2;

    觀察者模式是開發(fā)基于行為的應(yīng)用程序的有力手段,前端程序員可做的就是借助一個事件監(jiān)聽器替你處理各種行為,從而降低內(nèi)存消耗和提高互動性能。

    命令(Command)模式:將一個請求封裝為一個對象,從而使你可用不同的請求對客戶進(jìn)行參數(shù)化;對請求排隊(duì)或記錄請求日志,以及支持可取消的操作。

    命令對象是一個操作和用來調(diào)用這個操作的對象的結(jié)合體,所有的命名對象都有一個執(zhí)行操作,其用途就是調(diào)用命令對象所綁定的操作。示例:

    car Calculator={      add:function(x,y){         return x+y;      },      substract:function(x,y){         return x-y;      },      multiply:function(x,y){         return x*y;      },      divide:function(x,y){         return x/y;      }   }   Calculator.calc = function(command){      return Calculator[command.type](command.op1,command.opd2)   };   Calculator.calc({type:'add',op1:1,op2:1});   Calculator.calc({type:'substract',op1:5,op2:2});   Calculator.calc({type:'multiply',op1:5,op2:2});   Calculator.calc({type:'divide',op1:8,op2:4});

    命名模式的主要用途是把調(diào)用對象(用戶界面,API和代理等)與實(shí)現(xiàn)操作的對象隔離開,也就是說使對象間的互動方式需要更高的模塊化時都可以用到這種模式。

    職責(zé)鏈(Chain Of Responsibility)模式:為解除請求的發(fā)送者和接收者之間耦合,而使多個對象都有機(jī)會處理這個請求。將這些對象連成一條鏈,并沿著這條鏈傳遞該請求,直到有一個對象處理它。

    職責(zé)鏈由多個不同類型的對象組成:發(fā)送者是發(fā)出請求的對象,而接收者則是接收請求并且對其進(jìn)行處理或傳遞的對象,請求本身有時也是一個對象,它封裝著與操作有關(guān)的所有數(shù)據(jù)。

    典型的流程大致是:

    1.發(fā)送者知道鏈中***個接收者,它向這個接收者發(fā)出請求。

    2.每一個接收者都對請求進(jìn)行分析,然后要么處理它,要么將其往下傳。

    3.每一個接收者知道的其他對象只有一個,即它在鏈中的下家。

    4.如果沒有任何接收者處理請求,那么請求將從鏈上離開,不同的實(shí)現(xiàn)對此也有不同的反應(yīng),一般會拋出一個錯誤。

    職責(zé)鏈模式的適用范圍:1.有多個的對象可以處理一個請求,哪個對象處理該請求運(yùn)行時刻自動確定;2.想在不明確指定接收者的情況下,向多個對象中的一個提交一個請求;3.可處理一個請求的對象集合需要被動態(tài)指定。

    到此,關(guān)于“JavaScript閉包以及幾種設(shè)計(jì)模式的詳細(xì)介紹”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!


    本文題目:JavaScript閉包以及幾種設(shè)計(jì)模式的詳細(xì)介紹
    當(dāng)前地址:http://weahome.cn/article/jhshjp.html

    其他資訊

    在線咨詢

    微信咨詢

    電話咨詢

    028-86922220(工作日)

    18980820575(7×24)

    提交需求

    返回頂部