ES5中的继承

ES6中的继承

直接采用extends

 class A {
        constructor(v) {
          this.v = v;
          console.log(v);
        }
        run() {
            console.log("a");
        }
      }

      class B extends A {
        constructor(v) {
          super(v);
        }
        run(){
            super.run();    //执行class A中的run之后,继续执行下面的内容。
            console.log("b");
        }
      }

ES5中的继承

继承的写法:
子类.prototype=new 父类=父类.constructor

组合继承

父类:

  function Box(v){
      this.v=v;
      console.log(v);
  }
  Box.prototype.run=function(){

  }
  Box.prototype.a=10;

子类:

function Ball(v){
      Box.call(this,v);//冒充继承
      //在Ball的类中执行了Box
  }

  Ball.prototype=new Box();
  Object.defineProperty(Ball.prototype,"constructor",{
      value:Ball
  })
  var c=new Ball(3);
  console.log(c);

但是这种继承方式是存在BUG的:
Ball.prototype=new Box();在执行这句话的时候,new Box()时已经相当于执行了一次Box(),但此时什么参数都没有,打印的是undefined。而后实例化子类Ball的时候,又执行了一遍Ball,Ball中是Box的方法,所以执行了两遍

寄生式继承

为了解决上面执行两次函数的问题:
重新定义了一个内容为空的类继承父类,

父类:

 function Box(v){
        this.v=v;
        console.log(v);
    }
    Box.prototype.run=function(){

    }
    Box.prototype.a=10;

中介类:

function F(){

}
F.prototype=Box.prototype;

子类:

function Ball(v){
    Box.call(this,v);
}
Ball.prototype=new F();
Object.defineProperty(Ball.prototype,"constructor",{
    value:Ball
})

var c=new Ball(3);
console.log(c)

封装一个寄生式继承

   Function.prototype.extend = function (superClass) {
    function F() {} //创建一个新类用作继承中介(寄生)
    F.prototype = superClass.prototype; //给中介附上要继承的父类的原型
    var proto = this.prototype; //用proto存储子类原有的原型
    this.prototype = new F(); //继承于中介类,把实例化类的原型改变成为了中介父类的原型,且改变了this.prototype的地址。
    var names = Object.getOwnPropertyNames(proto);
    for (var i = 0; i < names.length; i++) {
      var desc = Object.getOwnPropertyDescriptor(proto, names[i]);  //获取子类原有的原型
      Object.defineProperty(this.prototype, names[i], desc);  //将子类自己的原型链重新给回到自身的原型链中
    }
    /* 
    同时为了避免一不小心被覆盖掉的子类的constructor,给他从新写回来以防万一
      */
    Object.defineProperty(this.prototype, "constructor", {
      value: this,
    });
    /* 
    方便后期方便调用父类的方法,给新类的对象属性中添加一个属性superClass,用来存储父类本身。
    同时也为了避免父类的constructor被什么东西一不小心覆盖了,也给他重新写回来。
      */
    this.prototype.superClass = superClass;
    if (superClass.prototype.constructor !== superClass) {
      Object.defineProperty(superClass.prototype, "constructor", {
        value: superClass,
      });
    }
  };

  function Box(v) {
    this.v = v;
    console.log(v);
  }
  Box.prototype.run = function () {
      console.log("a");
  };
  Box.prototype.a = 10;

  function Ball(v) {
    //这里就用到了封装的函数中临时加的对象属性superClass,存储的是父类
      this.superClass.apply(this,arguments); //类似于冒充式继承
      //super(5)
  }
  Ball.prototype.play=function(){

  }
  Ball.extend(Box); //调用继承方法
  Ball.prototype.run=function(){
      this.superClass.prototype.run.apply(this,arguments);
      //super.run(5)
      console.log("b");
  }

  var c=new Ball(5);
console.log(c); 
c.run();
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值