js继承

为何要继承

希望子类对象拥有父类的属性和方法

构造函数的继承

call写在子类构造函数中,将父构造函数中this指向由window指向子对象,并且执行父构造函数中的代码,(其实就相当于将父构造函数中的代码复制一份到子类构造函数中,将整个看做是子类构造器中的内容),所以改变了this指向,也继承了父类构造函数中的代码

    function People(){
      this.legs = 2;
    }
    function Man(){
      People.call(this);
      this.run = 3;
    }
    let m1 = new Man();
复制代码

call方法和apply方法的区别:从第二个参数起,call直接将这些参数依次传递给父构造函数,apply将这些参数放入数组中在传递给父构造函数。

   function People(name,legs){
      this.name = name;
      this.legs = legs;
    }
    function Man(name,legs){
      People.call(this,name,legs);
      //People.apply(this,[name,legs]);
      this.run = 3;
    }
    let m1 = new Man('yr', 2);
复制代码

注意: call和apply继承的只是构造函数中的属性和方法,通过原型prototype给父类添加的是无法继承的。

原型继承1:子类prototype直接引用父类prototype

   function People(name,legs){
      this.name = name;
      this.legs = legs;
    }
    People.prototype.showName = function(){
      console.log(this.name)
    }
    function Man(){
      this.run = 3;
    }
    Man.prototype = People.prototype;
    Man.prototype.showLegs= function(){
      console.log(this.legs)
    }
    let m1 = new Man('yr', 2);
复制代码

这种原型继承有个问题:就是直接将子类的prototype指向父类的prototype,这时他们两个使用的用一个内存地址,我们在子类Man的prototype上添加的showLegs也会添加在父类People的prototype上,显然这种方式是不合适的。

原型继承2:拷贝继承

   function People(name,legs){
      this.name = name;
      this.legs = legs;
    }
    People.prototype.showName = function(){
      console.log(this.name)
    }
    function Man(name,legs){
      People.call(this,name,legs)
      this.run = 3;
    }
    Man.prototype.showName= function(){
      console.log(this.legs)
    } 

   Man.prototype = {
      ...People.prototype,
      ...Man.prototype
    }
   
    let m1 = new Man('yr',18);
    let m2 = new Man('lyl',20);
复制代码

拷贝继承,使用扩展运算符将父类原型与子类原型合并,属性相同时,子类为准 (扩展运算符属性相同时,后面的覆盖前面的)

原型继承3:继承父类实例化对象

   function People(name,legs){
      this.name = 'yr';
      this.legs = 2;
    }
    People.prototype.showName = function(){
      console.log(this.name)
    }
    function Man(){
      this.run = 3;
    }
    Man.prototype = new People();
    Man.prototype.showLegs= function(){
      console.log(this.legs)
    }
    let m1 = new Man();
复制代码

这种子类继承了父类构造函数实例化对象,可以获得父类构造函数和原型上的属性和方法。但是存在一个问题,如果父类构造函数中包含引用类型值(数组,对象那类),就会出现以下问题

People的每个实例都有names属性,Man.prototype = new People();就相当于Man.prototype成为了People的一个实例,就像是创建了Man.prototype.names,那么通过Man创建出来的实例都会共享这个属性。

   function People(name,legs){
      this.names = ['yr','lyl'];
      this.legs = 2;
    }
    People.prototype.showName = function(){
      console.log(this.name)
    }
    function Man(){
      this.run = 3;
    }
    Man.prototype = new People(); 
    Man.prototype.showLegs= function(){
      console.log(this.legs)
    }
    let m1 = new Man();
    m1.names.push = 'xn';

    let m2 = new Man();
复制代码

此时我们需要的m2是不应该有新添加的xn,并且这种继承不能像父类构造函数传参

组合式继承

通过call或者apply继承构造函数,prototype继承父级的prototype

    function People(name,legs){
      this.names = name;
      this.legs = legs;
    }
    People.prototype.showName = function(){
      console.log(this.name)
    }
    function Man(name,legs){
      People.call(this,name,legs)
      this.run = 3;
    }
    Man.prototype = new People();
    Man.prototype.constructor = Man;
    Man.prototype.showLegs= function(){
      console.log(this.legs)
    }
    let m1 = new Man('yr',18);
    let m2 = new Man('lyl',20);
复制代码

组合式继承的原型链是

总结

当子类的prototype继承父类实例化对象时,原型链才发生真正的变化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值