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

首頁 > 編程 > JavaScript > 正文

全面分析JavaScript 繼承

2019-11-19 11:25:58
字體:
來源:轉載
供稿:網友

ES6之前,JavaScript并沒有繼承這一現有的機制。

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被賦予父類的實例,新創建的對象復制了父類的構造函數內的屬性和方法并且將原型_proto_指向了父類的原型對象,這樣就擁有了父類的原型對象上的屬性和方法與父類構造函數中復制的屬性和方法。

var instance = new Child();console.log(instance.getFatherValue()); //fatherconsole.log(instance.getChildValue()); //childconsole.log(instance instanceof Child); //trueconsole.log(instance instanceof Father); //trueconsole.log(instance instanceof Object); //trueconsole.log(Child instanceof Father); //falseconsole.log(Child.prototype instanceof Father); //true

缺點:

1.子類實例共用父類的公有引用屬性。

2.無法對父類構造函數內的屬性進行傳參初始化。

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']

構造函數繼承

//聲明父類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); //childAconsole.log(instanceB.companies); //['bigo','yy','uc']console.log(instanceB.val); //childB

對Child調用call,將子類中的變量在父類中執行一遍,然后父類給this綁定,所以子類繼承了父類的公有屬性。

缺點:

由于這種類型的繼承沒有設計原型prototype,所以父類的原型方法不會被子類繼承,而如果想被子類繼承就必須放在構造函數中,這樣創建出來的每個實例都會單獨擁有一份而不能共用。

組合繼承

//聲明父類function Father(val){this.companies =['bigo','yy','uc']this.val = val;}//聲明父類原型方法Father.prototype.getValue = function(){console.log(this.val);}//聲明子類function Child(val,newVal){//構造函數式繼承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(); //fatherAinstanceA.getNewValue(); //childAvar instanceB = new Child("fatherB","childB");console.log(instanceA.companies); //['bigo','yy','uc']instanceB.getValue(); //fatherBinstanceB.getNewValue(); //childB

缺點:

在使用構造函數繼承使用執行了一遍父類的構造函數,在實現子類原型的類式繼承再調用了一遍父類的構造函數,父類構造函數被調用了兩次。

原型式繼承

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); //shenzhenconsole.log(situationA.companies); //['bigo','yy','uc','tencent','baidu']console.log(situationB.area); //beijingconsole.log(situationB.companies); //['bigo','yy','uc','tencent','baidu']console.log(situation.area); //guangzhouconsole.log(situation.companies); //['bigo','yy','uc','tencent','baidu']

是類式繼承的一個封裝,其中的過渡對象就相當于類式繼承的子類,然后返回新的實例化對象。

缺點:

跟類式繼承一樣,父類的公有引用屬性被共有。

寄生式繼承

function inheritObject(obj){function F(){};F.prototype = obj;return new F();}var situation = {companies:['bigo','yy','uc'];area:'guangzhou';}function createSituation(obj){//通過原型繼承創建新對象var newObj = new inheritObject(obj);//定義新對象方法newObj.getArea = function(){console.log(newObj.area)}//返回對象return obj;}

只是在原型式繼承的基礎上添加了新屬性和方法,還是跟原型式繼承一樣的缺點。

寄生式組合繼承

function inheritObject(obj){function F(){};F.prototype = obj;return new F();}//傳遞參數 child,parent 子類父類function inheritPrototype(child,parent){//復制一份父類的原型副本保存在變量中;var fatherProto = inheritObject(father.prototype);//修正因為重寫子類原型導致子類的constructor屬性被修改;fatherProto.constructor = child;//設置子類的原型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){//構造函數式繼承Father.call(this,val);this.newVal = newVal;}//類式繼承Child.prototype = new Father();inheritPrototype(Child,Father);//聲明子類原型方法Child.prototype.getNewValue = function(){console.log(this.newVal);}

1.在構造函數繼承中我們已經調用了父類的構造函數,還差一個原型的副本

2.通過原型繼承得到副本,但是這時候fatherProto的constructor需要指向子類。

3.最后將副本fatherProto賦給子類的原型prototype。

總的來說,就是既要構造函數,又要原型繼承,但是又避免了組合繼承的兩次調用父類構造函數的問題,最大的改變式對子類原型賦予的式父類原型的一個引用。

var instanceA = new Child("fatherA","childA");instanceA.companies.push('nemo');console.log(instanceA.companies); //['bigo','yy','uc','nemo']instanceA.getValue(); //fatherAinstanceA.getNewValue(); //childAvar instanceB = new Child("fatherB","childB");console.log(instanceA.companies); //['bigo','yy','uc']instanceB.getValue(); //fatherBinstanceB.getNewValue(); //childB

注意點:

此時子類如果需要添加原型方法,必須通過prototype點語法一個個添加,否則會覆蓋掉繼承父類的原型對象。
ES6 新增了Class語法,Class 可以通過extends關鍵字實現繼承,這比 ES5 的通過修改原型鏈實現繼承,要清晰和方便很多。

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() // 1child instanceof Parent // true

class 實現繼承的核心在于使用 extends 表明繼承自哪個父類,并且在子類構造函數中必須調用 super,因為這段代碼可以看成 Parent.call(this, value)。

如果子類沒有定義constructor方法,這個方法會被默認添加。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永德县| 遵化市| 鹰潭市| 浑源县| 青阳县| 深圳市| 顺昌县| 南乐县| 上蔡县| 灵璧县| 洪江市| 盘山县| 开原市| 峨边| 兴业县| 肃北| 彩票| 壤塘县| 鄯善县| 防城港市| 汝阳县| 休宁县| 屏东县| 波密县| 佛教| 赤峰市| 桂平市| 平陆县| 安阳县| 休宁县| 彰化市| 竹北市| 临沧市| 舟山市| 娄底市| 河间市| 静宁县| 韶关市| 海原县| 镇原县| 宜宾市|