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();