您好,登錄后才能下訂單哦!
這篇文章主要講解了如何使用JavaScript類的封裝,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。
一,首先,為什么要使用封裝?
這是從信息的角度出發的,信息的隱藏是最終的目的,而封裝只不過是實現隱藏的一種方法。
這里我們需要明白一點就是:類的定義有如下的三種方式:
(第一種)門戶大開型方式 (第二種)用命令規范區別私有和公有的方式 (第三種)閉包
現在詳細描述一下每一種類的定義方式:
針對第一種,門戶大開類型
首先,我們來看一種情況
(1)聲明一個簡單的類,代碼如下
function Person(age,name) { this.name=name; this.age=age; }
(2)實例化類+調用
var p=new Person(-10,"小明"); alert(p.age)//結果出現年齡出現負數
從上述的運行結果中,我們可以看出程序可以正常執行,但這并符合實際,因為年齡出現 了負數,這不是我們想要的,我們需要一個能正確處理并產生與實際情況相符的解決方案。
為了能解決上述年齡出現的問題,我們可以這樣做:擴展類的原型鏈
Person.prototype={ checkAge:function (age) { if(0<age&&age<150){ return true; }else { return false; } } }
加上解決方案后,代碼如下
(1)基本類
function Person(age,name) { this.name=name; //調用方法判斷驗證 if(!this.checkAge(age)){ throw new Error("年齡必須在0-150之間"); } this.age=age; }
(2)年齡判斷驗證
Person.prototype={ checkAge:function (age) { if(0<age&&age<150){ return true; }else { return false; } } }
(3)調用
var p2=new Person(10,"小明"); alert(p2.age)
我們還可以給name添加一個讀取驗證,name為空時使用默認值 同樣是擴展類的原型鏈
代碼如下,
Person.prototype["getName"]=function () { return this.name||"我是默認的"; } //調用
var p3=new Person(10,""); alert(p3.getName())//結果為“我是默認的”
總結一下:當類被定義為門戶大開類型時會出現與實際不符合的情況 ,雖然我們可以加在類上擴展原型類加驗證方法解決,但是這樣會使類變得臃腫。
針對第二種,用命名規范區別私有和公有
步驟如下,
(1)定義類 在類中定義變量(私有和公有變量)+驗證方法的調用
//用命名規范來區別私有和公有 function Person(name,age,email) { //定義私有變量 this._name;//私有 this.setName(name);//只是方法的調用,方法中有驗證,而不是在類中驗證 this._age;//私有 this.setAge(age); this.email=email;//公有的 }
(2)在類的原型上面 擴展賦值方法
Person.prototype={//直接擴展至原型上,可以在本類的內部使用this調用 setName:function (name) { this._name=name; }, setAge:function (age) { //需要做判斷符號實際情況 if(age>0&&age<150){//驗證不在類中,類不會變的臃腫 this._age=age; }else { throw new Error("年齡必須是在0到150范圍內") } } }
(3)應用
var text1=new Person("測試",-10,"qq.com"); alert(text1._age)//-10 程序會報錯 這是我們想要的(說明驗證是對的)
var p2=new Person("測試2",10,"qq.cpm"); alert(p2._age)//程序正常運行 達到我們的目標
總結一下:在類的定義是使用命名規范來定義私有變量和公有變量,并將驗證方法和賦值方法擴展到本類的原型鏈上,在類中調用方法即可(會有返回值),這樣不會導致類的臃腫。
針對第三種,閉包實現封裝
這種方式有點像高級語言,在定義類是使用get,set方法實現數據的操作
(1)定義一個基本類(變量+操作變量的方法)
function Person(name,age,email) { //(1)聲明變量和對變量進行操作的get和set方法 this.email=email;//公有變量 //get方法 this.getName=function (name){ return this.name;//為什么是this調用呢?請看set方法 } this.getAge=function (age){ return this.age; } //set方法 這里相當于在類上的擴展 this.setName=function (name) { this.name=name;//Person.prototype.name 這里寫明了get中this的寫法的來源 } this.setAge=function (age) { if(age>0&&age<150){ this.age=age;//Person.prototype.name 這里寫明了get中this的寫法的來源 }else { throw new Error("年齡必須是在0到150范圍內"); } } //(2)寫一個構造函數 做初始化 實現閉包 確保set是在get之前的,不然get時會出現錯誤 this.init=function () { this.setName(name); this.setAge(age); } this.init();//顯示調用 }
(2)應用
var p=new Person("text",-10,"qq.com"); alert(p.age)//程序由于不符合實際而被阻斷,符合要求
注:額外的閉包寫法 var 方式
var _sex="M"; this.getSex=function () { return _sex; } this.setSex=function () { _sex=sex; }
總結一下:
(1)這里只是函數和屬性的簡單封裝,還有更為復雜是業務需要封裝,使用get和set方法時,需要一個構造函數用于兩者先后順序的初始化實現閉包,之后顯示調用,確保set是在get之前的。
(2)閉包的實現,是通過get和set實現的,this.方式賦值時沒有暴露在外面而是通過get,set方法實現閉包。
二,靜態化
普通屬性和函數是作用在對象上到,而靜態函數是定義到類上的。
第一種靜態函數的寫法 :寫在類上
(1)首先,定義一個簡單的類,例如
function Person(name,age) { this.name=name; this.age;age; this.showName=function () { alert(this.name); } }
(2)定義一個寫在類上的方法,Person.add --》(類.函數)或者(類.屬性),例如
Person.add=function (x,y) { return x+y; }
(3)應用
alert(Person.add(10,20));//結果為30
總結一下,該種定義方式有點類似于高級語言的靜態類,使用與高級語言的相同通過類直接調用。
第二種靜態函數的寫法 :使用類中類的方式完成每一個對象全擁有當前類中相同的屬性和函數 。注意: 類中類的方式是一次性賦值的
(1)類的定義格式如下
var cat=(function () { //私有靜態屬性 var AGE=1; function add(x,y) { return x+y; } return function () {//類中類 return返回的類中持有與上面類中相同的屬性與函數 則共同的AGE和add稱為靜態屬性和靜態函數 this.AGE=AGE; this.add=function (x,y) { return add(x,y) } } })()//實例化cat,實質是通過return實例化的
(2)應用
alert(new cat().add(1,3))//4 alert(new cat().AGE)//1
總結一下:從上面的代碼格式中我們不難看出在一個類中定義有私有的屬性和方法,與一個返回可以初始化本類私有靜態屬性和方法的類,該類我們稱為類中類。當我們實例化外層類時實質上是通過該類內部的類return實例化的。
封裝的優點:
(1)保護內部數據完整性是封裝一大用處
(2)對象的重構變得輕松,(如果沒有封裝你敢動正在運用的代碼嗎?) 答案肯定是不敢的。
(3)化模塊間的耦合
弊端:
(1)私有的方法會變得難以進行單元測試
(2)使用封裝意味著與復雜的代碼打交道
(3)最大問題封裝在JavaScript中很難實現 除非運用自如,否則到處封裝,使測試變得困難。
看完上述內容,是不是對如何使用JavaScript類的封裝有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。