国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 語(yǔ)言 > JavaScript > 正文

學(xué)習(xí)JavaScript設(shè)計(jì)模式(封裝)

2024-05-06 16:25:21
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
這篇文章主要帶領(lǐng)大家學(xué)習(xí)JavaScript設(shè)計(jì)模式,其中重點(diǎn)介紹封裝,舉例說(shuō)明封裝的思想,對(duì)封裝進(jìn)行詳細(xì)剖析,感興趣的小伙伴們可以參考一下
 

在JavaScript 中,并沒(méi)有對(duì)抽象類(lèi)和接口的支持。JavaScript 本身也是一門(mén)弱類(lèi)型語(yǔ)言。在封裝類(lèi)型方面,JavaScript 沒(méi)有能力,也沒(méi)有必要做得更多。對(duì)于JavaScript 的設(shè)計(jì)模式實(shí)現(xiàn)來(lái)說(shuō),不區(qū)分類(lèi)型是一種失色,也可以說(shuō)是一種解脫。

從設(shè)計(jì)模式的角度出發(fā),封裝在更重要的層面體現(xiàn)為封裝變化。

通過(guò)封裝變化的方式,把系統(tǒng)中穩(wěn)定不變的部分和容易變化的部分隔離開(kāi)來(lái),在系統(tǒng)的演變過(guò)程中,我們只需要替換那些容易變化的部分,如果這些部分是已經(jīng)封裝好的,替換起來(lái)也相對(duì)容易。這可以最大程度地保證程序的穩(wěn)定性和可擴(kuò)展性。

javascript封裝的的基本模式有3種:

1、使用約定優(yōu)先的原則,將所有的私有變量以_開(kāi)頭

 <script type="text/javascript">  /**   * 使用約定優(yōu)先的原則,把所有的私有變量都使用_開(kāi)頭   */  var Person = function (no, name, age)  {   this.setNo(no);   this.setName(name);   this.setAge(age);  }  Person.prototype = {   constructor: Person,   checkNo: function (no)   {    if (!no.constructor == "string" || no.length != 4)     throw new Error("學(xué)號(hào)必須為4位");   },   setNo: function (no)   {    this.checkNo(no);    this._no = no;   },    getNo: function ()   {    return this._no;   setName: function (name)   {    this._name = name;   },    getName: function ()   {    return this._name;   },    setAge: function (age)   {    this._age = age;   },    getAge: function ()   {    return this._age;   },    toString: function ()   {    return "no = " + this._no + " , name = " + this._name + " , age = " + this._age;   }  };  var p1 = new Person("0001", "小平果", "22");  console.log(p1.toString());  //no = 0001 , name = 小平果 , age = 22  p1.setNo("0003");  console.log(p1.toString());  //no = 0003 , name = 小平果 , age = 22  p1.no = "0004";  p1._no = "0004";  console.log(p1.toString()); //no = 0004 , name =小平果 , age = 22 </script>

看完代碼,是不是有種被坑的感覺(jué),僅僅把所有的變量以_開(kāi)頭,其實(shí)還是可以直接訪問(wèn)的,這能叫封裝么,當(dāng)然了,說(shuō)了是約定優(yōu)先嘛。

下劃線的這種用法這一個(gè)眾所周知的命名規(guī)范,它表明一個(gè)屬性僅供對(duì)象內(nèi)部使用,直接訪問(wèn)它或設(shè)置它可能會(huì)導(dǎo)致意想不到的后果。這有助于防止程序員對(duì)它的無(wú)意使用,卻不能防止對(duì)它的有意使用。

這種方式還是不錯(cuò)的,最起碼成員變量的getter,setter方法都是prototype中,并非存在對(duì)象中,總體來(lái)說(shuō)還是個(gè)不錯(cuò)的選擇。如果你覺(jué)得,這不行,必須嚴(yán)格實(shí)現(xiàn)封裝,那么看第二種方式。

2、嚴(yán)格實(shí)現(xiàn)封裝

<script type="text/javascript">  /**   * 使用這種方式雖然可以嚴(yán)格實(shí)現(xiàn)封裝,但是帶來(lái)的問(wèn)題是get和set方法都不能存儲(chǔ)在prototype中,都是存儲(chǔ)在對(duì)象中的   * 這樣無(wú)形中就增加了開(kāi)銷(xiāo)   */  var Person = function (no, name, age)  {   var _no , _name, _age ;   var checkNo = function (no)   {    if (!no.constructor == "string" || no.length != 4)     throw new Error("學(xué)號(hào)必須為4位");   };   this.setNo = function (no)   {    checkNo(no);    _no = no;   };   this.getNo = function ()   {    return _no;   }   this.setName = function (name)   {    _name = name;   }   this.getName = function ()   {    return _name;   }   this.setAge = function (age)   {    _age = age;   }   this.     getAge = function ()   {    return _age;   }   this.setNo(no);   this.setName(name);   this.setAge(age);  }  Person.prototype = {   constructor: Person,   toString: function ()   {    return "no = " + this.getNo() + " , name = " + this.getName() + " , age = " + this.getAge();   }  }  ;  var p1 = new Person("0001", "小平果", "22");  console.log(p1.toString());  //no = 0001 , name =小平果 , age = 22  p1.setNo("0003");  console.log(p1.toString());  //no = 0003 , name = 小平果 , age = 22  p1.no = "0004";  console.log(p1.toString()); //no = 0003 , name = 小平果 , age = 22 </script>

那么這與我們先前講過(guò)的其他創(chuàng)建對(duì)象的模式有什么不同呢,在上面的例子中,我們?cè)趧?chuàng)建和引用對(duì)象的屬性時(shí)總要使用this關(guān)鍵字。而在本例中,我們用var聲明這些變量。這意味著它們只存在于Person構(gòu)造器中。checkno函數(shù)也是用同樣的方式聲明的,因此成了一個(gè)私用方法。

需要訪問(wèn)這些變量和函數(shù)的方法只需要聲明在Person中即可。這些方法被稱為特權(quán)方法,因?yàn)樗鼈兪枪梅椒ǎ珔s能夠訪問(wèn)私用屬性和方法。為了在對(duì)象外部能訪問(wèn)這些特權(quán)函數(shù),它們的前面被加上了關(guān)鍵字this。因?yàn)檫@些方法定義于Person構(gòu)造器的作用域,所以它們能訪問(wèn)到私用屬性。引用這些屬性時(shí)并沒(méi)有使用this關(guān)鍵字,因?yàn)樗鼈儾皇枪_(kāi)的。所有取值器和賦值器方法都被改為不加this地直接引用這些屬性。

任何不需要直接訪問(wèn)的私用屬性的方法都可以像原來(lái)那樣在Person.prototype中聲明。像toString()方法。只有那些需要直接訪問(wèn)私用成員的方法才應(yīng)該被設(shè)計(jì)為特權(quán)方法。但特權(quán)方法太多又會(huì)占用過(guò)多的內(nèi)存,因?yàn)槊總€(gè)對(duì)象實(shí)例都包含所有特權(quán)方法的新副本。

看上面的代碼,去掉了this.屬性名,嚴(yán)格的實(shí)現(xiàn)了封裝,只能通過(guò)getter,setter訪問(wèn)成員變量了,但是存在一個(gè)問(wèn)題,所有的方法都存在對(duì)象中,增加了內(nèi)存的開(kāi)銷(xiāo)。

3、以閉包的方式封裝

<script type="text/javascript">  var Person = (function ()  {   //靜態(tài)方法(共享方法)   var checkNo = function (no)   {    if (!no.constructor == "string" || no.length != 4)     throw new Error("學(xué)號(hào)必須為4位");   };   //靜態(tài)變量(共享變量)   var times = 0;    //return the constructor.   return function (no, name, age)   {    console.log(times++); // 0 ,1 , 2    var no , name , age; //私有變量    this.setNo = function (no) //私有方法    {     checkNo(no);     this._no = no;    };    this.getNo = function ()    {     return this._no;    }    this.setName = function (name)    {     this._name = name;    }    this.getName = function ()    {     return this._name;    }    this.setAge = function (age)    {     this._age = age;    }    this.getAge = function ()    {     return this._age;    }    this.setNo(no);    this.setName(name);    this.setAge(age);   }  })();  Person.prototype = {   constructor: Person,   toString: function ()   {    return "no = " + this._no + " , name = " + this._name + " , age = " + this._age;   }  };  var p1 = new Person("0001", "小平果", "22");  var p2 = new Person("0002", "abc", "23");  var p3 = new Person("0003", "aobama", "24");  console.log(p1.toString());  //no = 0001 , name = 小平果 , age = 22  console.log(p2.toString());  //no = 0002 , name = abc , age = 23  console.log(p3.toString()); //no = 0003 , name = aobama , age = 24 </script>

上述代碼,js引擎加載完后,會(huì)直接執(zhí)行Person = 立即執(zhí)行函數(shù),然后此函數(shù)返回了一個(gè)子函數(shù),這個(gè)子函數(shù)才是new Person所調(diào)用的構(gòu)造函數(shù),又因?yàn)樽雍瘮?shù)中保持了對(duì)立即執(zhí)行函數(shù)中checkNo(no) ,times的引用,(很明顯的閉包)所以對(duì)于checkNo和times,是所有Person對(duì)象所共有的,創(chuàng)建3個(gè)對(duì)象后,times分別為0,1,2 。這種方式的好處是,可以使Person中需要復(fù)用的方法和屬性做到私有且對(duì)象間共享。

這里的私用成員特權(quán)成員仍然被聲明在構(gòu)造器。但那個(gè)構(gòu)造器卻從原來(lái)的普通函數(shù)變成了一個(gè)內(nèi)嵌函數(shù),并且被作為包含它的函數(shù)的返回值給變量Person。這就創(chuàng)建了一個(gè)閉包,你可以把靜態(tài)的私用成員聲明在里面。位于外層函數(shù)聲明之后的一對(duì)空括號(hào)很重要,其作用是代碼一載入就立即執(zhí)行這個(gè)函數(shù)。這個(gè)函數(shù)的返回值是另一個(gè)函數(shù),它被賦給Person變量,Person因此成了一個(gè)構(gòu)造函數(shù)。在實(shí)例華Person時(shí),所調(diào)用的這個(gè)內(nèi)層函數(shù)。外層那個(gè)函數(shù)只是用于創(chuàng)建一個(gè)可以用來(lái)存儲(chǔ)靜態(tài)成員的閉包。

在本例中,checkno被設(shè)計(jì)成為靜態(tài)方法,原因是為Person的每個(gè)實(shí)例都生成這個(gè)方法的一個(gè)新副本毫無(wú)道理。此外還有一個(gè)靜態(tài)屬性times,其作用在于跟蹤Person構(gòu)造器的總調(diào)用次數(shù)

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,大家可以更深入的學(xué)習(xí)了解封裝的意義。



注:相關(guān)教程知識(shí)閱讀請(qǐng)移步到JavaScript/Ajax教程頻道。
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 海安县| 从化市| 龙胜| 长沙市| 屯留县| 威海市| 庆阳市| 织金县| 江源县| 永济市| 毕节市| 东乌| 泰州市| 丹凤县| 乌拉特后旗| 泸溪县| 衡山县| 萍乡市| 湖州市| 崇礼县| 晋宁县| 嘉禾县| 青田县| 定兴县| 贵德县| 南平市| 黄陵县| 延寿县| 南部县| 五寨县| 泰宁县| 祁阳县| 新余市| 新宁县| 安多县| 达州市| 汕尾市| 庆元县| 乌兰察布市| 平利县| 林甸县|