js中ES5的继承

js的前期是没有类的这种说法,更不用说是继承了,于是创建出了很多继承的方式,经历很多个版本,实现了类似继承的方法。

3种有问题的继承方式

1.原型式继承

function Box(v){        //父类Box的创建
    this.v=v;
    console.log(v);
}
Box.prototype.run=function(){   //Box原型方法的创建

}
Box.prototype.a=10;

function Ball(v){   //子类的创建
   
}
Ball.prototype=new Box();  //原型式继承 就是父类的实例化赋值到子类的原型上
Object.defineProperty(Ball.prototype,"constructor",{   //没有constructor,只能自己创建
    value:Ball
})
var c=new Ball(3);   //但是constructor还是不能像ES6一样
console.log(c);

2.组合继承(原型继承和冒充继承)

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

}
Box.prototype.a=10;

function Ball(v){   
//这是冒充继承(改变父类this指向)
   Box.call(this,v);  //为了解决constructor不能正常工作    把Box的this指向改为Ball(子类)的,但是new  Ball的时候,Box的constructor可以正常工作,new Box还是不能解决
}
Ball.prototype=new Box();  
Object.defineProperty(Ball.prototype,"constructor",{   
    value:Ball
})
var c=new Ball(3);  
console.log(c);

完全实现继承的方式

  • 寄生式继承(原型继承,冒充继承,中间函数)
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;  //子类的原型  原因:后面的new  F会覆盖原来的属性,所以提前拿出来
    this.prototype = new F();   //中间类的实例赋值给子类原型
    var names = Object.getOwnPropertyNames(proto);  //获取子类原型上的所有方法和属性名
    for (var i = 0; i < names.length; i++) {      //遍历原来的属性名,new F()后,重新弄上去
        var desc = Object.getOwnPropertyDescriptor(proto, names[i]);
        Object.defineProperty(this.prototype, names[i], desc);
    }
    Object.defineProperty(this.prototype, "constructor", {
        value: this,
    });
    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) {   constructor中的super
     this.superClass.apply(this,arguments);
  }
  Ball.prototype.play=function(){

  }
  Ball.extend(Box);
  Ball.prototype.run=function(){    子类方法中继承父类的这个方法   相当于ES6中的super.run();
     this.superClass.prototype.run.apply(this,arguments);
     console.log("b");
  }

  var c=new Ball(5);
console.log(c);
c.run();
posted on 2020-08-15 17:17  94Lucky  阅读(115)  评论(0编辑  收藏  举报