小編給大家分享一下JavaScript繼承怎么實現(xiàn),相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
成都創(chuàng)新互聯(lián)公司專注于企業(yè)營銷型網(wǎng)站、網(wǎng)站重做改版、二道網(wǎng)站定制設(shè)計、自適應(yīng)品牌網(wǎng)站建設(shè)、H5響應(yīng)式網(wǎng)站、商城開發(fā)、集團公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計等建站業(yè)務(wù),價格優(yōu)惠性價比高,為二道等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
ES6之前,JavaScript并沒有繼承這一現(xiàn)有的機制。
ES5的繼承方式
類式繼承
//聲明父類 function Father(){ this.fatherVal = 'father'; } //為父類添加共有方法 Father.prototype.getFatherValue = function(){ return this.fatherVal; } //聲明子類 function Child(){ this.childVal = 'child'; } //繼承父類 Child.prototype = new Father(); //為子類添加共有方法 Child.prototype.getChildValue = function(){ return this.childVal; }
子類的prototype被賦予父類的實例,新創(chuàng)建的對象復(fù)制了父類的構(gòu)造函數(shù)內(nèi)的屬性和方法并且將原型_proto_指向了父類的原型對象,這樣就擁有了父類的原型對象上的屬性和方法與父類構(gòu)造函數(shù)中復(fù)制的屬性和方法。
var instance = new Child(); console.log(instance.getFatherValue()); //father console.log(instance.getChildValue()); //child console.log(instance instanceof Child); //true console.log(instance instanceof Father); //true console.log(instance instanceof Object); //true console.log(Child instanceof Father); //false console.log(Child.prototype instanceof Father); //true
缺點:
1.子類實例共用父類的公有引用屬性。
2.無法對父類構(gòu)造函數(shù)內(nèi)的屬性進行傳參初始化。
function Father(){ this.companies =['bigo','yy','uc'] } funtion Child(){} Child.prototype = new Father(); var instanceA = new Child(); var instanceB = new Child(); console.log(instanceB.companies); //['bigo','yy','uc'] instanceA.companies.push('nemo'); console.log(instanceB.companies); //['bigo','yy','uc','nemo']
構(gòu)造函數(shù)繼承
//聲明父類 function Father(val){ this.companies =['bigo','yy','uc'] this.val = val; } //聲明父類原型方法 Father.prototype.getCom = function(){ console.log(this.companies); } //聲明子類 function Child(val){ //繼承 Father.call(this,val); } var instanceA = new Child('childA'); var instanceB = new Child('childB'); instanceA.companies.push('nemo'); console.log(instanceA.companies); //['bigo','yy','uc','nemo'] console.log(instanceA.val); //childA console.log(instanceB.companies); //['bigo','yy','uc'] console.log(instanceB.val); //childB
對Child調(diào)用call,將子類中的變量在父類中執(zhí)行一遍,然后父類給this綁定,所以子類繼承了父類的公有屬性。
缺點:
由于這種類型的繼承沒有設(shè)計原型prototype,所以父類的原型方法不會被子類繼承,而如果想被子類繼承就必須放在構(gòu)造函數(shù)中,這樣創(chuàng)建出來的每個實例都會單獨擁有一份而不能共用。
組合繼承
//聲明父類 function Father(val){ this.companies =['bigo','yy','uc'] this.val = val; } //聲明父類原型方法 Father.prototype.getValue = function(){ console.log(this.val); } //聲明子類 function Child(val,newVal){ //構(gòu)造函數(shù)式繼承 Father.call(this,val); this.newVal = newVal; } //類式繼承 Child.prototype = new Father(); //聲明子類原型方法 Child.prototype.getNewValue = function(){ console.log(this.newVal); } var instanceA = new Child("fatherA","childA"); instanceA.companies.push('nemo'); console.log(instanceA.companies); //['bigo','yy','uc','nemo'] instanceA.getValue(); //fatherA instanceA.getNewValue(); //childA var instanceB = new Child("fatherB","childB"); console.log(instanceA.companies); //['bigo','yy','uc'] instanceB.getValue(); //fatherB instanceB.getNewValue(); //childB
缺點:
在使用構(gòu)造函數(shù)繼承使用執(zhí)行了一遍父類的構(gòu)造函數(shù),在實現(xiàn)子類原型的類式繼承再調(diào)用了一遍父類的構(gòu)造函數(shù),父類構(gòu)造函數(shù)被調(diào)用了兩次。
原型式繼承
function inheritObject(obj){ function F(){}; F.prototype = obj; return new F(); } var situation = { companies:['bigo','yy','uc']; area:'guangzhou'; } var situationA = inheritObject(situation); situationA.area = 'shenzhen'; situationA.companies.push('tencent'); var situationB = inheritObject(situation); situationB.area = 'beijing'; situationB.companies.push('baidu'); console.log(situationA.area); //shenzhen console.log(situationA.companies); //['bigo','yy','uc','tencent','baidu'] console.log(situationB.area); //beijing console.log(situationB.companies); //['bigo','yy','uc','tencent','baidu'] console.log(situation.area); //guangzhou console.log(situation.companies); //['bigo','yy','uc','tencent','baidu']
是類式繼承的一個封裝,其中的過渡對象就相當(dāng)于類式繼承的子類,然后返回新的實例化對象。
缺點:
跟類式繼承一樣,父類的公有引用屬性被共有。
寄生式繼承
function inheritObject(obj){ function F(){}; F.prototype = obj; return new F(); } var situation = { companies:['bigo','yy','uc']; area:'guangzhou'; } function createSituation(obj){ //通過原型繼承創(chuàng)建新對象 var newObj = new inheritObject(obj); //定義新對象方法 newObj.getArea = function(){ console.log(newObj.area) } //返回對象 return obj; }
只是在原型式繼承的基礎(chǔ)上添加了新屬性和方法,還是跟原型式繼承一樣的缺點。
寄生式組合繼承
function inheritObject(obj){ function F(){}; F.prototype = obj; return new F(); } //傳遞參數(shù) child,parent 子類父類 function inheritPrototype(child,parent){ //復(fù)制一份父類的原型副本保存在變量中; var fatherProto = inheritObject(father.prototype); //修正因為重寫子類原型導(dǎo)致子類的constructor屬性被修改; fatherProto.constructor = child; //設(shè)置子類的原型 child.prototype = fatherProto; } //聲明父類 function Father(val){ this.companies =['bigo','yy','uc'] this.val = val; } //聲明父類原型方法 Father.prototype.getValue = function(){ console.log(this.val); } //聲明子類 function Child(val,newVal){ //構(gòu)造函數(shù)式繼承 Father.call(this,val); this.newVal = newVal; } //類式繼承 Child.prototype = new Father(); inheritPrototype(Child,Father); //聲明子類原型方法 Child.prototype.getNewValue = function(){ console.log(this.newVal); }
1.在構(gòu)造函數(shù)繼承中我們已經(jīng)調(diào)用了父類的構(gòu)造函數(shù),還差一個原型的副本
2.通過原型繼承得到副本,但是這時候fatherProto的constructor需要指向子類。
3.最后將副本fatherProto賦給子類的原型prototype。
總的來說,就是既要構(gòu)造函數(shù),又要原型繼承,但是又避免了組合繼承的兩次調(diào)用父類構(gòu)造函數(shù)的問題,最大的改變式對子類原型賦予的式父類原型的一個引用。
var instanceA = new Child("fatherA","childA"); instanceA.companies.push('nemo'); console.log(instanceA.companies); //['bigo','yy','uc','nemo'] instanceA.getValue(); //fatherA instanceA.getNewValue(); //childA var instanceB = new Child("fatherB","childB"); console.log(instanceA.companies); //['bigo','yy','uc'] instanceB.getValue(); //fatherB instanceB.getNewValue(); //childB
注意點:
此時子類如果需要添加原型方法,必須通過prototype點語法一個個添加,否則會覆蓋掉繼承父類的原型對象。
ES6 新增了Class語法,Class 可以通過extends關(guān)鍵字實現(xiàn)繼承,這比 ES5 的通過修改原型鏈實現(xiàn)繼承,要清晰和方便很多。
Class 繼承
class Parent { constructor(value) { this.val = value } getValue() { console.log(this.val) } } class Child extends Parent { constructor(value) { super(value) } } let child = new Child(1) child.getValue() // 1 child instanceof Parent // true
class 實現(xiàn)繼承的核心在于使用 extends 表明繼承自哪個父類,并且在子類構(gòu)造函數(shù)中必須調(diào)用 super,因為這段代碼可以看成 Parent.call(this, value)。
如果子類沒有定義constructor方法,這個方法會被默認(rèn)添加。
以上是“JavaScript繼承怎么實現(xiàn)”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!
本文標(biāo)題:JavaScript繼承怎么實現(xiàn)
分享鏈接:http://bm7419.com/article22/gegdjc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站排名、網(wǎng)站改版、品牌網(wǎng)站設(shè)計、商城網(wǎng)站、動態(tài)網(wǎng)站、關(guān)鍵詞優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)