继承方式知多少

原型链继承

每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型。如果原型是另一个类型的实例呢?

这意味着这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数。这样就在实例和原型之间构造了一条原型链

通过修改子类的原型为父类的实例,从而实现子类可以访问到父类构造函数以及原型上的属性或者方法。

function Parent() {
  //属性
  this.name = 'fedaily';
  //实例方法
  this.sleep = function(){
      console.log(this.name + "正在睡觉");
  }
}
//父类原型方法
Parent.prototype.eat = function(food = 'apple') {
  console.log(this.name +'正在吃'+ food);
}

//空子类
function Child() {}

// 这里也可以直接写出Child.prototype = Parent.prototype
// 但是这样就不能访问到父类的构造函数的属性了,即this.name
Child.prototype = new Parent();
Child.prototype.name = 'Bob';

var child = new Child();
child.eat();

缺点:

  • 在包含有引用类型的数据时,会被所有的子类实例共享,其中一个子类实例进行修改,会导致所有其他子类实例的这个值都会改变
  • 在创建子类型的时候不能向超类型传递参数

构造函数继承call

通过修改父类构造函数this实现的继承。

function Parent() {
  //属性
  this.name = 'Amy';
  //实例方法
  this.sleep = function(){
      console.log(this.name + "正在睡觉");
  }
}

function Child(){
 //继承了Parent
  Parent.call(this);  
  this.name = "BOB";
}
let child = new Child();

组合继承

同时结合原型链继承、构造函数继承,是使用最多的继承方式。

function Parent(){
  this.name = "Amy";
  this.age = 20;
}
Parent.prototype.eat = function(){
  return this.name + this.age + 'eat sleep';
}

function Child(){
    //第一次调用父类构造函数
    Parent.call(this);
    this.name = 'Bob';
    this.topic = 'fe';
}

//第二次调用父类构造函数
Child.prototype = new Parent();
//需要重新设置子类的constructor,Child.prototype = new Parent()相当于子类的原型对象完全被覆盖了
Child.prototype.construct = Child;

let child = new Child();
child.eat();

寄生式组合继承

在组合继承的基础上,解决了父类构造函数调用两次的问题

function Parent(){
    this.name = 'Amy';
    this.age = 20;
}

//父类原型方法
Parent.prototype.eat = function(){
    return this.name + this.age + 'eat sleep';
}

//子类
function Child(){
    //继承父类属性
    Parent.call(this);
    this.name = 'Bob';
    this.age = 28;
}

//继承父类方法(执行匿名函数)
(function(){
    //创建空类
    let Super = function(){};
    Super.prototype = Parent.protype;
    //父类的实例作为子类的原型
    Child.prototype = new Super();
})();

// 修复构造函数指向问题
Child.prototype.constructor = Child;

let child = new Child();

原型式继承(实例继承)

function Parent(){
    this.name = 'Amy';
    this.age = 20;
}

function Child(){
	let instance = new Parent();
    instance.name = "Bob";
    instance.topic = 'fe';
    return instance;
}

let child = new Child();

ES6继承

ES6继承是使用关键字先创建父类的实例对象this,最后在子类class中修改this

class Parent{
    constructor(){
        this.name = 'Amy';
        this.age = 20;
    }
    eat(){
        console.log(`${this.name} ${this.age} eat food`);
    }
}

//子类继承
class Child extends Parent{
    constructor(){
        super();
    }
    eat(){
        super.eat();
        this.topic = 'fe';
    }
}

let child = new Child();
child.eat();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

eynoZzzzc

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值