亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

學習JavaScript設計模式(封裝)

2024-05-06 16:25:21
字體:
來源:轉載
供稿:網友
這篇文章主要帶領大家學習JavaScript設計模式,其中重點介紹封裝,舉例說明封裝的思想,對封裝進行詳細剖析,感興趣的小伙伴們可以參考一下
 

在JavaScript 中,并沒有對抽象類和接口的支持。JavaScript 本身也是一門弱類型語言。在封裝類型方面,JavaScript 沒有能力,也沒有必要做得更多。對于JavaScript 的設計模式實現來說,不區分類型是一種失色,也可以說是一種解脫。

從設計模式的角度出發,封裝在更重要的層面體現為封裝變化。

通過封裝變化的方式,把系統中穩定不變的部分和容易變化的部分隔離開來,在系統的演變過程中,我們只需要替換那些容易變化的部分,如果這些部分是已經封裝好的,替換起來也相對容易。這可以最大程度地保證程序的穩定性和可擴展性。

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

1、使用約定優先的原則,將所有的私有變量以_開頭

 <script type="text/javascript">  /**   * 使用約定優先的原則,把所有的私有變量都使用_開頭   */  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("學號必須為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>

看完代碼,是不是有種被坑的感覺,僅僅把所有的變量以_開頭,其實還是可以直接訪問的,這能叫封裝么,當然了,說了是約定優先嘛。

下劃線的這種用法這一個眾所周知的命名規范,它表明一個屬性僅供對象內部使用,直接訪問它或設置它可能會導致意想不到的后果。這有助于防止程序員對它的無意使用,卻不能防止對它的有意使用。

這種方式還是不錯的,最起碼成員變量的getter,setter方法都是prototype中,并非存在對象中,總體來說還是個不錯的選擇。如果你覺得,這不行,必須嚴格實現封裝,那么看第二種方式。

2、嚴格實現封裝

<script type="text/javascript">  /**   * 使用這種方式雖然可以嚴格實現封裝,但是帶來的問題是get和set方法都不能存儲在prototype中,都是存儲在對象中的   * 這樣無形中就增加了開銷   */  var Person = function (no, name, age)  {   var _no , _name, _age ;   var checkNo = function (no)   {    if (!no.constructor == "string" || no.length != 4)     throw new Error("學號必須為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>

那么這與我們先前講過的其他創建對象的模式有什么不同呢,在上面的例子中,我們在創建和引用對象的屬性時總要使用this關鍵字。而在本例中,我們用var聲明這些變量。這意味著它們只存在于Person構造器中。checkno函數也是用同樣的方式聲明的,因此成了一個私用方法。

需要訪問這些變量和函數的方法只需要聲明在Person中即可。這些方法被稱為特權方法,因為它們是公用方法,但卻能夠訪問私用屬性和方法。為了在對象外部能訪問這些特權函數,它們的前面被加上了關鍵字this。因為這些方法定義于Person構造器的作用域,所以它們能訪問到私用屬性。引用這些屬性時并沒有使用this關鍵字,因為它們不是公開的。所有取值器和賦值器方法都被改為不加this地直接引用這些屬性。

任何不需要直接訪問的私用屬性的方法都可以像原來那樣在Person.prototype中聲明。像toString()方法。只有那些需要直接訪問私用成員的方法才應該被設計為特權方法。但特權方法太多又會占用過多的內存,因為每個對象實例都包含所有特權方法的新副本。

看上面的代碼,去掉了this.屬性名,嚴格的實現了封裝,只能通過getter,setter訪問成員變量了,但是存在一個問題,所有的方法都存在對象中,增加了內存的開銷。

3、以閉包的方式封裝

<script type="text/javascript">  var Person = (function ()  {   //靜態方法(共享方法)   var checkNo = function (no)   {    if (!no.constructor == "string" || no.length != 4)     throw new Error("學號必須為4位");   };   //靜態變量(共享變量)   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引擎加載完后,會直接執行Person = 立即執行函數,然后此函數返回了一個子函數,這個子函數才是new Person所調用的構造函數,又因為子函數中保持了對立即執行函數中checkNo(no) ,times的引用,(很明顯的閉包)所以對于checkNo和times,是所有Person對象所共有的,創建3個對象后,times分別為0,1,2 。這種方式的好處是,可以使Person中需要復用的方法和屬性做到私有且對象間共享。

這里的私用成員特權成員仍然被聲明在構造器。但那個構造器卻從原來的普通函數變成了一個內嵌函數,并且被作為包含它的函數的返回值給變量Person。這就創建了一個閉包,你可以把靜態的私用成員聲明在里面。位于外層函數聲明之后的一對空括號很重要,其作用是代碼一載入就立即執行這個函數。這個函數的返回值是另一個函數,它被賦給Person變量,Person因此成了一個構造函數。在實例華Person時,所調用的這個內層函數。外層那個函數只是用于創建一個可以用來存儲靜態成員的閉包。

在本例中,checkno被設計成為靜態方法,原因是為Person的每個實例都生成這個方法的一個新副本毫無道理。此外還有一個靜態屬性times,其作用在于跟蹤Person構造器的總調用次數。

以上就是本文的全部內容,希望對大家的學習有所幫助,大家可以更深入的學習了解封裝的意義。



注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国内精品400部情侣激情| 九九热精品视频在线播放| 国产成人亚洲综合91| 中文字幕日韩电影| 欧美激情在线有限公司| 夜色77av精品影院| 狠狠躁夜夜躁人人爽超碰91| 欧美日韩一区二区免费在线观看| 这里只有精品丝袜| 黑人精品xxx一区一二区| 日本一区二区在线免费播放| 国产综合视频在线观看| 欧美成人精品一区| 日韩精品在线观看网站| 久久久久久18| 欧美日韩第一页| 久久中国妇女中文字幕| 亚洲91精品在线| 57pao成人国产永久免费| 视频在线观看一区二区| 国产91在线播放九色快色| 久久国产精品影视| 亚洲日韩第一页| 性色av一区二区三区红粉影视| 亚洲石原莉奈一区二区在线观看| 日韩av电影在线免费播放| 日韩免费视频在线观看| 亚洲精品久久久久中文字幕欢迎你| 欧美午夜久久久| 国产精品高清网站| 亚洲美女av黄| 久久91亚洲精品中文字幕| 日韩网站免费观看| 国产婷婷色综合av蜜臀av| 亚洲色图50p| 日韩美女在线观看| 欧美性xxxx在线播放| 在线观看成人黄色| 色婷婷综合久久久久中文字幕1| 欧美理论电影在线观看| 欧美激情视频在线免费观看 欧美视频免费一| 亚洲最大av网| 久久五月天色综合| 日韩一区二区久久久| 日本久久精品视频| 成人在线小视频| 亚洲 日韩 国产第一| 欧美另类在线播放| 最近2019中文字幕一页二页| …久久精品99久久香蕉国产| 久久久影视精品| 91老司机在线| 最新69国产成人精品视频免费| 日韩av中文在线| 亚洲国产中文字幕久久网| 亚洲精品色婷婷福利天堂| 久久中文字幕一区| 国产精品电影一区| 91精品久久久久久久久不口人| 亚洲精品乱码久久久久久按摩观| 日韩欧美aaa| 日韩成人性视频| 精品久久中文字幕久久av| 亚洲精品乱码久久久久久金桔影视| 日韩美女毛茸茸| 亚洲欧洲一区二区三区在线观看| 久久久国产影院| 粉嫩av一区二区三区免费野| 91情侣偷在线精品国产| 国产成人一区二| 欧美精品www| 中文字幕欧美日韩va免费视频| 69久久夜色精品国产7777| 久久久国产精品视频| 成人福利在线视频| 日韩av电影手机在线观看| 国产精品久久久久久一区二区| 日本视频久久久| 亚洲欧美制服中文字幕| 欧美激情中文网| 日韩美女福利视频| 国产成人av网| 精品中文字幕在线2019| 亚洲成年人在线播放| 欧美大片在线影院| 久久av红桃一区二区小说| 91欧美激情另类亚洲| 国内精品久久久久久| 亚洲精品视频在线观看视频| 欧美在线不卡区| 亚洲国产精品大全| 亚洲自拍偷拍视频| 亚洲丁香久久久| 国产精品视频最多的网站| 日韩电影免费在线观看中文字幕| 成人福利网站在线观看11| 欧美在线视频播放| 91av在线网站| 久久精品欧美视频| 国产丝袜视频一区| 日本国产高清不卡| 日韩av中文字幕在线免费观看| 国内精品久久久久| 久久久久久久久久久成人| 日韩成人久久久| 欧美亚洲国产另类| 久久久亚洲国产| 日韩精品电影网| 91久久久久久久久久久| 欧美在线视频网站| 日韩在线观看免费网站| 国产热re99久久6国产精品| 国产亚洲成精品久久| 欧美日韩性生活视频| 久久久成人的性感天堂| 国产精品va在线播放| 国产精品福利片| 精品中文字幕在线| 91黑丝高跟在线| 国产免费久久av| 日韩av片电影专区| 97人人做人人爱| 久久久久国产一区二区三区| 亚洲欧美综合精品久久成人| 欧美日韩国产在线播放| 亚洲国产美女精品久久久久∴| 海角国产乱辈乱精品视频| 欧美日韩国产区| 亚洲999一在线观看www| 日本一区二区在线免费播放| 中文日韩在线观看| 国产精品88a∨| 国产精品电影久久久久电影网| 久久国产精彩视频| 日韩综合视频在线观看| 欧美性黄网官网| 97热在线精品视频在线观看| 日韩欧美大尺度| 色综合久久久888| www.国产一区| 日韩欧美aⅴ综合网站发布| 久久久久久网站| 麻豆国产精品va在线观看不卡| 久久久久久久电影一区| 亚洲免费一级电影| 激情懂色av一区av二区av| 国产精品电影久久久久电影网| 91精品91久久久久久| 亚洲老板91色精品久久| 国产精品福利片| 中文字幕亚洲欧美在线| 日韩一区二区欧美| 亚洲黄一区二区| 欧美日韩亚洲激情| 97欧美精品一区二区三区| 久久久久久久999精品视频| 国产成人综合一区二区三区| 精品久久久久久中文字幕| 国产在线视频不卡| 国产一区二区三区四区福利| 97视频色精品| 日韩成人激情视频| 国产91在线高潮白浆在线观看| 伊人久久久久久久久久|