真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

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

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

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),和平企業(yè)網(wǎng)站建設(shè),和平品牌網(wǎng)站建設(shè),網(wǎng)站定制,和平網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,和平網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力??沙浞譂M足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。

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

1、原型鏈

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

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

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

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

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

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

    //第一個(gè)構(gòu)造函數(shù);有一個(gè)屬性和一個(gè)原型方法
    function SuperType(){
        this.property=true;
    } 
    
    SuperType.prototype.getSuperValue=function(){
        return this.property
    }


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

    console.log(instance.getSuperValue())  //true 先查找instance這個(gè)實(shí)例有沒有此方法;顯然沒有,再查找SubType原型對象有沒有此方法;也沒有,再查找SubType原型對象的原型對象;顯然是存在的

注意:instance的constructor現(xiàn)在指向的是SuperType這個(gè)構(gòu)造函數(shù);因?yàn)樵瓉淼腟ubType.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的實(shí)例;每個(gè)默認(rèn)原型都有個(gè)_proto_指針指向Object.prototype;因此自定義類型都繼承如toString,valueOf的方法

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

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

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

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

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

    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)慎定義方法

注意:給原型對象添加方法,一定放在替換原型的后面,因?yàn)榉旁谔鎿Q原型之前是找不到了,原型會(huì)被重寫的;

注意:在通過原型鏈繼承時(shí),不能使用對象字面量創(chuàng)建原型方法,因?yàn)橐矔?huì)重寫原型鏈;

    function SuperType(){
        this.property=true;
    } 
    
    SuperType.prototype.getSuperValue=function(){
        return this.property
    }
    
    function SubType(){
        this.subproperty=false
    }
    
    //繼承SuperType
    SubType.prototype=new SuperType()
    
    //使用字面量添加新方法,導(dǎo)致上一行無效   因?yàn)楝F(xiàn)在的原型替換了Object實(shí)例而非SuperType的實(shí)例,關(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ù)的原型時(shí),引用類型值就會(huì)變成原型上的屬性,就會(huì)被另一函數(shù)的實(shí)例所共享。

    function SuperType(){
       this.colors=["yellow","red","olive"]
    }

    function SubType(){
    }

    SubType.prototype=new SuperType()  //color實(shí)際上就是原型上的了

    var instance1=new SubType()
    instance1.colors.push("purple")
    var instance2=new SubType()

    console.log(instance1.colors==instance2.colors)  //true

2、創(chuàng)建子類型實(shí)例時(shí),不能向超類型的構(gòu)造函數(shù)傳遞參數(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)時(shí)間寫一下

1、原型式繼承

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

    function object(o){      //本質(zhì)上object()函數(shù)對其中對象的淺復(fù)制
        function F(){}      //創(chuàng)建一個(gè)新的構(gòu)造函數(shù)
        F.prototype=o      //構(gòu)造函數(shù)原型為傳入的對象
      return new F()      //返回構(gòu)造函數(shù)的實(shí)例
    }

    var person={
        name:"double",
        friends:["tom","jack","mike"]
    }

    var person1=object(person)   //事實(shí)上為原型共享
    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ī)范原型式的繼承,有個(gè)Object.create()來方便,IE9以上可以;只是想一個(gè)對象和另一個(gè)對象保持類似的情況,完全可以這種方法

    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()接受兩個(gè)參數(shù),一個(gè)為作為新對象原型的對象,一個(gè)為新對象定義額外屬性對象
    var person={
        name:"double",
        friends:["tom","jack","mike"]
    }

    var person1=Object.create(person,{
         name:{ 
            value:"single"  //每個(gè)屬性都是通過自己描述符定義的
         }
    })

2、寄生式繼承

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

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

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

  function object(o){
     function F(){}
     F.prototype=o
     return new F()
  }


  function inheritPrototype(subType,superType){
     var prototype=object(superType)    //創(chuàng)建對象  (superType實(shí)例)
     prototype.constructor=subType     //增強(qiáng)對象
     subType.prototype=prototype      //指定對象  (原型賦予實(shí)例)
  }
  

   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添加個(gè)方法
      alert(this.age)
   }

   var person1=new SubType("double","man",34)
   console.log(person1.name)  //SuperType 這是個(gè)Bug
   console.log(person1.sex)   //man
   console.log(person1.colors) //["red"]
   person1.sayAge()       //34

到此,差不多結(jié)束啦,感謝你對創(chuàng)新互聯(lián)的支持,希望我們整理的內(nèi)容能夠幫助到你。


當(dāng)前標(biāo)題:徹底理解js面向?qū)ο笾^承
文章來源:http://weahome.cn/article/gjihji.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部