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

首頁 > 編程 > JavaScript > 正文

徹底理解js面向對象之繼承

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

說道這個繼承,了解object-oriented的朋友都知道,大多oo語言都有兩種,一種是接口繼承(只繼承方法簽名);一種是實現繼承(繼承實際的方法)

奈何js中沒有簽名,因而只有實現繼承,而且靠的是原型鏈實現的。下面正式的說一說js中繼承那點事兒

1、原型鏈

原型鏈:實現繼承的主要方法,利用原型讓一個引用類型繼承另一個引用類型的屬性和方法。

回顧:構造函數,原型,實例三者的關系

每一個構造函數都有一個原型對象(Person.prototype);原型對象都包含指向構造函數的指針(constructor);每個實例都包含指向原型對象的指針(看不見的_proto_指針)

原型鏈是怎么來的呢?

某個構造函數的原型對象是另一個構造函數的實例;這個構造函數的原型對象就會有個(看不見的_proto_指針)指向另一個構造函數的原型對象;

那么另一個原型對象又是其他的構造函數實例又會怎么樣,就這樣層層遞進,形成原型鏈;來具體看一下吧

    //第一個構造函數;有一個屬性和一個原型方法    function SuperType(){        this.property=true;    }         SuperType.prototype.getSuperValue=function(){        return this.property    }    //第二個構造函數;目前有一個屬性    function SubType(){        this.subproperty=false    }        //繼承了SuperType;SubType原型成了SuperType的實例;實際就是重寫SubType的原型對象;給SuperType原型對象繼承了    SubType.prototype=new SuperType()        //現在這個構造函數有兩個屬性(一個本身的subproperty,一個繼承的存在原型對象的property);兩個方法(一個原型對象的getSubValue,一個原型對象的原型對象的getSuperValue)    SubType.prototype.getSubValue=function(){        return this.subproperty    }        var instance=new SubType()  //創建第二個構造函數的實例    console.log(instance.getSuperValue())  //true 先查找instance這個實例有沒有此方法;顯然沒有,再查找SubType原型對象有沒有此方法;也沒有,再查找SubType原型對象的原型對象;顯然是存在的

注意:instance的constructor現在指向的是SuperType這個構造函數;因為原來的SubType.prototype被重寫了,其內部的constructor也就隨著SubType.prototype的原型對象的constructor指向構造函數SuperType;至于原型搜索機制是怎么樣運行的,請仔細看上面的代碼,相信你是可以的

1.1完整的原型

在原型那節已經提了些,還是再說一下。完整的原型包括Object。

所有函數的默認原型都是Object的實例;每個默認原型都有個_proto_指針指向Object.prototype;因此自定義類型都繼承如toString,valueOf的方法

而Object.prototype的_proto_指針指向null來結束原型鏈。以Person構造函數為例,看看完整的原型鏈圖

1.2原型和實例的關系判斷

第一種使用instanceof操作符: 測試實例和原型鏈中出現的構造函數,結果為true

第二種使用isPrototypeOf()方法: 只要是原型鏈中出現過的原型,都可以說是該原型鏈所派生的實例的原型

    console.log(instance instanceof Object)   //都為true    console.log(instance instanceof SuperType)    console.log(instance instanceof SubType)       console.log(Object.prototype.isPrototypeOf(instance)) //都為true    console.log(SuperType.prototype.isPrototypeOf(instance))    console.log(SubType.prototype.isPrototypeOf(instance))

1.3謹慎定義方法

注意:給原型對象添加方法,一定放在替換原型的后面,因為放在替換原型之前是找不到了,原型會被重寫的;

注意:在通過原型鏈繼承時,不能使用對象字面量創建原型方法,因為也會重寫原型鏈;

    function SuperType(){        this.property=true;    }         SuperType.prototype.getSuperValue=function(){        return this.property    }        function SubType(){        this.subproperty=false    }        //繼承SuperType    SubType.prototype=new SuperType()        //使用字面量添加新方法,導致上一行無效   因為現在的原型替換了Object實例而非SuperType的實例,關系中斷    SubType.prototype={       getSubValue:function(){           return this.subproperty;       },       somOtherMethod:function(){           return false       }    };    var instance=new SubType()    console.log(instance.getSuperValue())  //error

1.4原型鏈的問題

1、包含引用類型值的原型:當實例是另一函數的原型時,引用類型值就會變成原型上的屬性,就會被另一函數的實例所共享。

    function SuperType(){       this.colors=["yellow","red","olive"]    }    function SubType(){    }    SubType.prototype=new SuperType()  //color實際上就是原型上的了    var instance1=new SubType()    instance1.colors.push("purple")    var instance2=new SubType()    console.log(instance1.colors==instance2.colors)  //true

2、創建子類型實例時,不能向超類型的構造函數傳遞參數(沒有辦法在不影響所有對象實例的情況下,給超類型的構造函數傳遞參數)

2、借助構造函數

為了解決原型中包含引用類型值帶來的問題,利用構造函數來解決

在子類型構造函數的內部調用超類型構造函數(函數是特定環境中執行代碼的對象,可以通過apply或call調用)

    function SuperType(){        this.color=["yellow","red","olive"]    }    function SubType(){        //繼承了SuperType        SuperType.call(this)    }    var instance1=new SubType()    instance1.color.push("purple")    var instance2=new SubType()    console.log(instance1.color)  //["yellow","red","olive","purple"]    console.log(instance2.color)  //["yellow","red","olive"]    //傳遞參數    function SuperType(name){       this.name=name    }    function SubType(){        SuperType.call(this,"double")        this.age=12    }    var instance1=new SubType()    console.log(instance1.name)  //double    console.log(instance1.age)  //12

問題:僅僅借鑒構造函數,那么避免不了構造函數的問題,方法都在構造函數定義了,函數無法復用

3、組合繼承(常用的還是組合,和原型與構造結合一樣)

    function SuperType(name){        this.name=name;        this.color=["yellow","red","olive"];    }    SuperType.prototype.sayName=function(){        console.log(this.name);    }     function SubType(name,age){        //繼承屬性,創建屬性副本        SuperType.call(this,name);        this.age=age;    }        //繼承屬性和方法,只是原型中屬性被后來的函數調用生成的屬性副本遮蓋    SubType.prototype=new SuperType();    alert(SubType.prototype.constructor)  //指向的是SuperType    SubType.prototype.constructor=SubType; //將constructor回歸到SubType構造函數身上    SubType.prototype.sayAge=function(){        console.log(this.age)    }            var instance1=new SubType("double",23)    instance1.color.push("pink")    console.log(instance1.color)     //["yellow","red","olive","pink"]    instance1.sayName()         //double    instance1.sayAge()          //23    var instance2=new SubType("single",34)    console.log(instance2.color)     //["yellow","red","olive"]    instance2.sayName()         //single    instance2.sayAge()          //34

還有其他的繼承,花點時間寫一下

1、原型式繼承

克羅克福德寫的;借助原型可以基于已有的對象創建新對象,同時不必創建自定義類型

    function object(o){      //本質上object()函數對其中對象的淺復制        function F(){}      //創建一個新的構造函數        F.prototype=o      //構造函數原型為傳入的對象      return new F()      //返回構造函數的實例    }    var person={        name:"double",        friends:["tom","jack","mike"]    }    var person1=object(person)   //事實上為原型共享    person1.name="grey"    person1.friends.push("single")        console.log(person1.friends)  //["tom", "jack", "mike", "single"]    var person2=object(person)    person2.name="red"    console.log(person2.friends)   //["tom", "jack", "mike", "single"]

ES5為了規范原型式的繼承,有個Object.create()來方便,IE9以上可以;只是想一個對象和另一個對象保持類似的情況,完全可以這種方法

    var person={        name:"double",        friends:["tom","jack","mike"]    }    var person1=Object.create(person)    person1.name="single"    person1.friends.push("singles")    var person2=Object.create(person)    console.log(person1.friends==person2.friends) //true    //Object.create()接受兩個參數,一個為作為新對象原型的對象,一個為新對象定義額外屬性對象    var person={        name:"double",        friends:["tom","jack","mike"]    }    var person1=Object.create(person,{         name:{             value:"single"  //每個屬性都是通過自己描述符定義的         }    })

2、寄生式繼承

思路和原型式繼承一脈相承,創建一個用于封裝繼承過程的函數,內部通過方式增強對象,返回對象;主要考慮對象時使用

function object(o){       function F(){}       F.prototype=o       return new F()    }    function createPerson(original){       var clone=object(original)   //繼承原型       clone.sayName=function(){            alert("name")       }       return clone    }    var person={       name:"double",       friends:["single","tom","jack"]    }    var person1=createPerson(person)    person1.sayName()  //name   引用類型值還是共享的

3、寄生組合繼承

組合繼承是繼承中常常用到的,但是會調用兩次超類型構造函數;寄生組合繼承就是為了解決這個問題的

  function object(o){     function F(){}     F.prototype=o     return new F()  }  function inheritPrototype(subType,superType){     var prototype=object(superType)    //創建對象  (superType實例)     prototype.constructor=subType     //增強對象     subType.prototype=prototype      //指定對象  (原型賦予實例)  }     function SuperType(name,sex){      this.name=name      this.sex=sex      this.colors=["red"]   }   SuperType.prototype.sayName=function(){     alert(this.name)   }   function SubType(name,sex,age){      SuperType.call(this,name,sex)      this.age=age   }   inheritPrototype(SubType,SuperType)    //目前subType.prototype什么都沒有   SubType.prototype.sayAge=function(){   //為subType.prototype添加個方法      alert(this.age)   }   var person1=new SubType("double","man",34)   console.log(person1.name)  //SuperType 這是個Bug   console.log(person1.sex)   //man   console.log(person1.colors) //["red"]   person1.sayAge()       //34

到此,差不多結束啦,感謝你對武林網的支持,希望我們整理的內容能夠幫助到你。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲第一色中文字幕| 一区二区亚洲精品国产| 日韩av大片在线| 精品中文字幕久久久久久| 中文字幕欧美精品日韩中文字幕| 国产成人鲁鲁免费视频a| 欧美日韩成人网| 国产一区欧美二区三区| 国产视频综合在线| 亚洲自拍偷拍一区| 欧美日韩性生活视频| 亚洲一区二区三区四区视频| 国产欧美最新羞羞视频在线观看| 91精品国产高清久久久久久91| 国产精品天天狠天天看| 精品少妇v888av| 在线电影中文日韩| 国外日韩电影在线观看| 亚洲欧美中文字幕| 欧美午夜影院在线视频| 亚洲一区二区自拍| 日韩在线观看免费av| 日韩毛片在线看| 日本一区二区三区四区视频| 亚洲精品久久久久| 国产日韩av在线播放| 国产精品稀缺呦系列在线| 中文字幕在线精品| 最近2019年手机中文字幕| 国产91成人video| 日本一区二三区好的精华液| 亚洲精品美女久久| 欧美亚洲一级片| 久久久久久久国产精品视频| 精品久久久久久中文字幕一区奶水| 国产精品久久久久久中文字| 欧美激情欧美狂野欧美精品| 自拍偷拍亚洲精品| 国产成人精品在线| 日韩精品久久久久久福利| 久久免费成人精品视频| 国产日韩中文字幕| 国产精品观看在线亚洲人成网| 热久久免费国产视频| 91成人免费观看网站| 综合激情国产一区| 国产美女精品视频| 久久久精品电影| 亚洲免费伊人电影在线观看av| 日韩美女视频在线观看| 欧美激情按摩在线| 久久久精品亚洲| 国内免费久久久久久久久久久| 亚洲精品99999| 久久久久久噜噜噜久久久精品| 国产精品成人免费电影| 欧美成人午夜激情| 日韩成人在线视频观看| 激情成人在线视频| 国产精品稀缺呦系列在线| 在线观看视频亚洲| 不卡av电影院| 国产精品久久久久国产a级| 成人福利在线观看| 亚洲一区二区黄| 国产精品久久久久秋霞鲁丝| 在线播放国产精品| 国产精品久久久久久久久久久不卡| 国产日韩精品在线| 国产精品v片在线观看不卡| 欧美国产日韩一区二区| 亚洲精品aⅴ中文字幕乱码| 亚洲精品成人久久久| 欧美精品久久久久久久久| 亚洲欧美日韩中文视频| 亚洲天堂成人在线视频| 国产精品视频一区二区三区四| 久久精品国产精品亚洲| 亚洲欧美日韩综合| 午夜精品久久久久久久男人的天堂| 55夜色66夜色国产精品视频| 国产不卡av在线| 亚洲欧美一区二区精品久久久| 国产在线精品成人一区二区三区| 伊人男人综合视频网| 欧美性一区二区三区| 欧美电影在线免费观看网站| 精品视频在线播放免| 国产成人精品一区二区三区| 91久久国产精品| 欧美性生交大片免网| 国产精品香蕉国产| 欧美一级电影免费在线观看| 亚洲a在线播放| 久久综合伊人77777| 国产裸体写真av一区二区| 成人黄色中文字幕| 亚洲欧美一区二区三区情侣bbw| 欧美日韩一区二区精品| 精品国产91久久久久久老师| 大荫蒂欧美视频另类xxxx| 国产日产亚洲精品| 欧美激情18p| 亚洲男女自偷自拍图片另类| www.国产一区| 欧美交受高潮1| 欧美成人精品h版在线观看| 2019中文字幕在线观看| 欧美成人午夜剧场免费观看| 国产午夜精品一区二区三区| 成人情趣片在线观看免费| 欧美激情一区二区三级高清视频| 国产成一区二区| 91高清免费视频| 国产精品香蕉在线观看| 青青久久aⅴ北条麻妃| 日韩欧美国产免费播放| 成人精品在线观看| 欧美电影免费在线观看| 中文字幕综合在线| 久久99精品国产99久久6尤物| 国产91在线播放精品91| 精品国产91乱高清在线观看| 久久综合久久美利坚合众国| 国产精品久久av| 亚洲18私人小影院| 久久人人爽国产| 992tv在线成人免费观看| 国产在线播放91| 成人妇女免费播放久久久| 欧美第一淫aaasss性| 久久天堂电影网| 欧美精品一本久久男人的天堂| 久久精品一区中文字幕| 在线看福利67194| 亚洲在线第一页| 欧美精品在线免费| 美女少妇精品视频| 精品亚洲一区二区三区在线观看| 国产精品视频永久免费播放| 国产va免费精品高清在线| 亚洲欧美日韩在线一区| 91在线免费看网站| 国产精品影片在线观看| 亚洲国产精品成人va在线观看| 久久精品国产亚洲精品2020| 精品国模在线视频| 成人字幕网zmw| 一区二区三区久久精品| 日韩欧美国产免费播放| 亚洲欧美精品中文字幕在线| 亚洲免费视频观看| 亚洲iv一区二区三区| 中文字幕国产精品久久| 欧美成人精品一区| 久久久久久久91| 国产精品福利片| 欧美激情一区二区三级高清视频| 亚洲乱码国产乱码精品精天堂| 亚洲一区二区三区视频| 欧美极品美女电影一区| 精品色蜜蜜精品视频在线观看| 久久高清视频免费| 欧美性猛交xxxx免费看|