1. 程式人生 > >js中的幾種繼承方法

js中的幾種繼承方法

JS作為面向物件的弱型別語言,繼承也是其非常強大的特性之一。

繼承:子承父業;一個原本沒有某些方法或屬性的物件,統一寫方法,拿到了另外一個物件的屬性和方法

下面是js中的幾種繼承方式

1.改變this指向繼承(建構函式繼承):繼承建構函式中的屬性和方法

 function Parent(n){
        this.name = n;
        this.skill = function(){
            console.log(this.name + "是籃球運動員");     //櫻木花道是籃球運動員
                                                       //澤北榮治是籃球運動員
        }
    }
    Parent.prototype.init = function(){
        console.log(123)                               //123
    }

    // function P2(){
    //     this.a = 10;
    // }
    // function P3(){
    //     this.b = 20;
    // }
    // function P4(){
    //     this.c = 30;
    // }
    
    function Child(n){
        // Parent.bind(this,n)();
        // P2.bind(this)()
        // P3.bind(this)()
        // P4.bind(this)()

        // Parent.call(this,n);

        Parent.apply(this,arguments);
    }

    var p = new Parent("櫻木花道");
    console.log(p)
    p.skill();       //
    p.init()

    var c = new Child("澤北榮治");
    console.log(c)
    c.skill();           //   
    // console.log(c.a)
    // console.log(c.b)
    // console.log(c.c)
    // c.init()

優點:簡單方便易操作,可以多繼承

缺點:只能繼承建構函式,不能繼承原型

2.原型物件繼承:繼承原型

function Parent(n){
        this.name = n;
    }
    Parent.prototype.skill = function(){
        console.log(this.name + "是鑑定師");       //大老王是鑑定師
                                                 //小老王是鑑定師
    }

    function Child(n){
        this.name = n;
    }

    // 注意:物件的深淺拷貝
    for(var i in Parent.prototype){
        Child.prototype[i] = Parent.prototype[i];
    }


    var p = new Parent("大老王");
    console.log(p)                            //Parent {name: "大老王"}
    p.skill();

    var c = new Child("小老王");
    console.log(c)                            //Child {name: "小老王"}
    c.skill();

優點:簡單,方便,可以繼承原型身上的方式和屬性
缺單:只能繼承原型,不方便傳參

3.原型鏈繼承:通過給Child設定原型為Parent的例項的方式,給Child添加了一層原型鏈的方式

 function Parent(n){
        this.name = n;
    }
    Parent.prototype.skill = function(){
        console.log(this.name + "是鑑定師");           //大老王是鑑定師
    }

    function Child(){}
    Child.prototype = new Parent("小老王");

    Child.prototype.skill = function(){
        console.log(this.name+"是運動員")             //小老王是運動員
    } 

    var p = new Parent("大老王");
    console.log(p)                                 //Parent {name: "大老王"}
    p.skill();
    // p是例項(物件),有__proto__屬性,指向Parent.prototype

    var c = new Child();
    console.log(c);                              //Child {}
    c.skill();
    // c是例項(物件),有__proto__屬性,指向Child.prototype,是Parent的例項(物件),有__proto__屬性,指向Parent.prototype

優點:既能繼承原型,又能繼承建構函式
缺點:複雜,不方便傳參

4.混合繼承:建構函式繼承+原型物件繼承

 function Parent(n){
        this.name = n;
    }
    Parent.prototype.skill = function(){
        console.log(this.name + "是鑑定師");              //大老王是鑑定師
    }

    function P2(){
        this.a = 10;
    }
    P2.prototype.init = function(){
        console.log("hello")                        //hello
    }

    function Child(n){
        Parent.call(this,n)
        P2.call(this)
    }
    for(var i in Parent.prototype){
        Child.prototype[i] = Parent.prototype[i]
    }
    for(var i in P2.prototype){
        Child.prototype[i] = P2.prototype[i]
    }

    Child.prototype.skill = function(){
        console.log(123)                            //123
    }
   

    var p = new Parent("大老王");
    console.log(p)                           //Parent {name: "大老王"}
    p.skill();

    var c = new Child("小老王");
    console.log(c)                          //Child {name: "小老王", a: 10}
    c.skill();
    c.init();

優點:既能繼承建構函式又能繼承原型,方便傳參,多繼承

缺點:複雜

常用的繼承方式之一

5.ES6的class繼承

class Parent{
        constructor(n) {
            this.name = n
        }
        skill(){
            console.log(this.name + "是鑑定師")         //大老王是鑑定師
                                                      //小老王是鑑定師
        }
    }

    class Child extends Parent{
        constructor(n){
            super(n)
        }
    }

    var p = new Parent("大老王");
    console.log(p)                              //Parent {name: "大老王"}
    p.skill();

    var c = new Child("小老王");                //Child {name: "小老王"}
    console.log(c)
    c.skill();

優點:簡單方便易操作,語法層面的繼承,屬性和方法都能繼承,引數很好處理

缺點:相容性

忽略相容,常用的繼承方式之