<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

        徹底理解js面向?qū)ο笾^承

        來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 22:20:15
        文檔

        徹底理解js面向?qū)ο笾^承

        徹底理解js面向?qū)ο笾^承:說道這個繼承,了解object-oriented的朋友都知道,大多oo語言都有兩種,一種是接口繼承(只繼承方法簽名);一種是實現(xiàn)繼承(繼承實際的方法) 奈何js中沒有簽名,因而只有實現(xiàn)繼承,而且靠的是原型鏈實現(xiàn)的。下面正式的說一說js中繼承那點(diǎn)事兒 1、原型鏈
        推薦度:
        導(dǎo)讀徹底理解js面向?qū)ο笾^承:說道這個繼承,了解object-oriented的朋友都知道,大多oo語言都有兩種,一種是接口繼承(只繼承方法簽名);一種是實現(xiàn)繼承(繼承實際的方法) 奈何js中沒有簽名,因而只有實現(xiàn)繼承,而且靠的是原型鏈實現(xiàn)的。下面正式的說一說js中繼承那點(diǎn)事兒 1、原型鏈

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

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

        1、原型鏈

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

        回顧:構(gòu)造函數(shù),原型,實例三者的關(guān)系

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

        原型鏈?zhǔn)窃趺磥淼哪兀?/p>

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

        那么另一個原型對象又是其他的構(gòu)造函數(shù)實例又會怎么樣,就這樣層層遞進(jìn),形成原型鏈;來具體看一下吧

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

        注意:instance的constructor現(xiàn)在指向的是SuperType這個構(gòu)造函數(shù);因為原來的SubType.prototype被重寫了,其內(nèi)部的constructor也就隨著SubType.prototype的原型對象的constructor指向構(gòu)造函數(shù)SuperType;至于原型搜索機(jī)制是怎么樣運(yùn)行的,請仔細(xì)看上面的代碼,相信你是可以的

        1.1完整的原型

        在原型那節(jié)已經(jīng)提了些,還是再說一下。完整的原型包括Object。

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

        而Object.prototype的_proto_指針指向null來結(jié)束原型鏈。以Person構(gòu)造函數(shù)為例,看看完整的原型鏈圖

        1.2原型和實例的關(guān)系判斷

        第一種使用instanceof操作符: 測試實例和原型鏈中出現(xiàn)的構(gòu)造函數(shù),結(jié)果為true

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

         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謹(jǐn)慎定義方法

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

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

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

        1.4原型鏈的問題

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

         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、創(chuàng)建子類型實例時,不能向超類型的構(gòu)造函數(shù)傳遞參數(shù)(沒有辦法在不影響所有對象實例的情況下,給超類型的構(gòu)造函數(shù)傳遞參數(shù))

        2、借助構(gòu)造函數(shù)

        為了解決原型中包含引用類型值帶來的問題,利用構(gòu)造函數(shù)來解決

        在子類型構(gòu)造函數(shù)的內(nèi)部調(diào)用超類型構(gòu)造函數(shù)(函數(shù)是特定環(huán)境中執(zhí)行代碼的對象,可以通過apply或call調(diào)用)

         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"]
        
        
         //傳遞參數(shù)
         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

        問題:僅僅借鑒構(gòu)造函數(shù),那么避免不了構(gòu)造函數(shù)的問題,方法都在構(gòu)造函數(shù)定義了,函數(shù)無法復(fù)用

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

         function SuperType(name){
         this.name=name;
         this.color=["yellow","red","olive"];
         }
        
         SuperType.prototype.sayName=function(){
         console.log(this.name);
         }
         
         function SubType(name,age){
         //繼承屬性,創(chuàng)建屬性副本
         SuperType.call(this,name);
         this.age=age;
         }
         
         //繼承屬性和方法,只是原型中屬性被后來的函數(shù)調(diào)用生成的屬性副本遮蓋
         SubType.prototype=new SuperType();
        
         alert(SubType.prototype.constructor) //指向的是SuperType
        
         SubType.prototype.constructor=SubType; //將constructor回歸到SubType構(gòu)造函數(shù)身上
         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

        還有其他的繼承,花點(diǎn)時間寫一下

        1、原型式繼承

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

         function object(o){ //本質(zhì)上object()函數(shù)對其中對象的淺復(fù)制
         function F(){} //創(chuàng)建一個新的構(gòu)造函數(shù)
         F.prototype=o //構(gòu)造函數(shù)原型為傳入的對象
         return new F() //返回構(gòu)造函數(shù)的實例
         }
        
         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為了規(guī)范原型式的繼承,有個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()接受兩個參數(shù),一個為作為新對象原型的對象,一個為新對象定義額外屬性對象
         var person={
         name:"double",
         friends:["tom","jack","mike"]
         }
        
         var person1=Object.create(person,{
         name:{ 
         value:"single" //每個屬性都是通過自己描述符定義的
         }
         })

        2、寄生式繼承

        思路和原型式繼承一脈相承,創(chuàng)建一個用于封裝繼承過程的函數(shù),內(nèi)部通過方式增強(qiáng)對象,返回對象;主要考慮對象時使用

        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、寄生組合繼承

        組合繼承是繼承中常常用到的,但是會調(diào)用兩次超類型構(gòu)造函數(shù);寄生組合繼承就是為了解決這個問題的

         function object(o){
         function F(){}
         F.prototype=o
         return new F()
         }
        
        
         function inheritPrototype(subType,superType){
         var prototype=object(superType) //創(chuàng)建對象 (superType實例)
         prototype.constructor=subType //增強(qiáng)對象
         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

        到此,差不多結(jié)束啦,感謝你對腳本之家的支持,希望我們整理的內(nèi)容能夠幫助到你。

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        徹底理解js面向?qū)ο笾^承

        徹底理解js面向?qū)ο笾^承:說道這個繼承,了解object-oriented的朋友都知道,大多oo語言都有兩種,一種是接口繼承(只繼承方法簽名);一種是實現(xiàn)繼承(繼承實際的方法) 奈何js中沒有簽名,因而只有實現(xiàn)繼承,而且靠的是原型鏈實現(xiàn)的。下面正式的說一說js中繼承那點(diǎn)事兒 1、原型鏈
        推薦度:
        標(biāo)簽: js 了解 對象
        • 熱門焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: vvvv99日韩精品亚洲| 在线看片无码永久免费视频| 在线观看永久免费视频网站| 亚洲精品无码少妇30P| 毛片免费在线观看网址| 99久久国产亚洲综合精品| 好吊妞在线新免费视频| 亚洲欧美日韩中文字幕在线一区 | 中国一级特黄高清免费的大片中国一级黄色片| 国产成人免费ā片在线观看| 免费大片av手机看片| 亚洲乱码日产精品a级毛片久久| 羞羞视频免费网站日本| 国产成人亚洲精品狼色在线| 亚洲免费无码在线| 久久久久亚洲AV成人无码网站| 99热在线观看免费| 亚洲国产亚洲综合在线尤物| 精品久久洲久久久久护士免费 | 国产一精品一aⅴ一免费| 九九全国免费视频| 国产成人精品日本亚洲网站| 1区2区3区产品乱码免费| 亚洲综合精品成人| 亚洲国产婷婷香蕉久久久久久| 中国国产高清免费av片| 亚洲国产精品日韩在线| 国产乱子伦精品免费无码专区 | 99ri精品国产亚洲| 免费无码黄十八禁网站在线观看| 亚洲AV性色在线观看| 国产性爱在线观看亚洲黄色一级片 | 亚洲最大黄色网址| 免费一级毛片女人图片| 久久精品成人免费观看| 狠狠色香婷婷久久亚洲精品| 国产成人毛片亚洲精品| 2021久久精品免费观看| 一级做a爰性色毛片免费| 亚洲综合一区二区精品久久| 免费播放特黄特色毛片|