JS继承的6种方式

定义一个父类Person:

function Person(name){
    this.name=name;
}
Person.prototype.age=25;
Person.prototype.show=function(){
  console.log(this.name);
}

 

1.原型链继承

子类的原型是父类的实例。

function subType(){}
subType.prototype=new Person();

// 测试
let p1=new subType();
p1.name;    //undefined,可以访问,但是name未初始化所以为undefined
p1.age;    //25

特点:父类的构造函数中的属性和方法,以及原型中的属性和方法都放入了子类的原型中,都可以访问得到。

问题:

1.原型中的属性和方法,在实例中是共享的。构造函数中的属性和方法在实例中不共享。这说明,父类中的所有属性,在子类的实例中都将共享,假如父类有一个数组,那么子类的实例将共享这个属性,当有一个子类实例改变这个数组的项时,所有的实例中的这个属性都会随之改变。

2.创建子类实例时,不能向超类型构造函数中传递参数。

 

2.借用构造函数

在子类构造函数中调用父类构造函数。

function subType(name){
    Person.call(this,name);
}

// 测试
let p2=new subPerson("zhangsan");
p2.name;    //"zhangsan"
p2.age;    //undefined

特点:解决了方法一的问题,所有的子类实例都将不共享属性和方法,互不影响,并且可以传值。

问题:

1.构造函数中的方法不能共享复用,每个实例都将拥有相同的方法。

2.父类的原型中的方法和属性在子类中不可见。

 

3.组合继承

组合原型链方法和借用构造函数方法

function subType(name){
    Person.call(this,name);
}
subType.prototype=new Person();

//测试
let p3=new subType("lisi");
p3.name;    //"lisi"
p3.show();    //"lisi"
p3.age;    //25

特点:既可以继承父类原型中的属性和方法,又能将父类的构造函数放入子类构造函数中。

缺点:父类的实例属性在子类的实例和原型中都有,属性重复了。

 

4.原型式继承

以一个对象为基础,创建一个新对象,并将旧对象作为新对象的原型,返回这个新对象的实例。

function clone(o){
    function fn(){};
    fn.prototype=o;
    return new fn();
}
var subType=clone(superType);
//测试
let person=new Person("wangwu");
var subType=clone(Person); let p4
=new subType(); p4.name; //"wangwu" p4.age; //25

特点:要求必须有一个对象可以作为另一个对象的基础。返回的是一个对象。可以向超类型构造函数中传递参数。

缺点:父类的实例属性不能被继承。

 

5.寄生式继承

构造函数中通过某种方式创建父类对象,然后为这个对象添加属性和函数,并返回这个对象。

function clone(o){
    function fn(){};
    fn.prototype=o;
    return new fn();
}
function inhire(original){
    let obj=clone(original);
    obj.sayHi=function(){
        alert("Hi");
    }
  return obj; }
var suubType=inheir(SuperType);

特点:创建对象部分不必要固定方式,只要可以返回一个父类对象就可。返回的是一个加入了自定义方法和属性的对象。

缺点:自定义的方法不能共享复用。

 

6.寄生组合式继承

使用寄生式继承来继承超类型的原型。使用借用构造函数的方法继承父类的构造函数属性和方法,并添加自己的构造函数属性和方法。

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

function inheritPrototype(subType,superType){
    let p=object(superType.prototype);
    p.constructor=subType;
    subType.prototype=p;
}

//子类
function subType(name){
    Person.call(this,name);
}
inheritPrototype(subType,Person);

特点:避免了组合式继承中原型和构造函数中重复继承父类的构造函数中的属性和方法。

posted @ 2020-05-05 23:51  程嘿嘿  阅读(721)  评论(0编辑  收藏  举报