继承

112 阅读2分钟

ES5继承

【寄生组合继承】避免两次调用父类构造函数,通过赋值直接继承父类的原型
完美方法

function Person(name){
	this.name = name;
	this.hobby  = ['唱歌','踢球','跑步']
}
Person.prototype.eat = function(){
	console.log("好吃");
}
//子类
function Child(age,name){
	this.age = age;
	Person.call(this,name) //借用构造函数
}
var proObj = Object.create(Person.prototype);
proObj.constructor = Child;
Child.prototype = proObj;

【组合继承】构造函数设计模式 + 原型设计模式
方法好理解,但有一个弱点:父类构造函数被调用了两次)

function MakeCar(price, color, performance) {
  this.price = price;
  this.color = color;
  this.run = () => {
    console.log(performance);
  };
}
function MakeCarChild(brand, ...args) {
  MakeCar.call(this, ...args);
  //new MakeCarChild的时候,这个语句相当于执行MakeCar,所以实例上有price,color,run这些属性
  //(也就是说继承了MakeCar)
  this.brand = brand;
}
MakeCarChild.prototype = new MakeCar();
// 原型继承父类的构造器,将MakeCarChild.prototype.__proto__ = MakeCar.prototype,
//不然子类不能继承父类原型上的属性
MakeCarChild.prototype.constructor = MakeCarChild; // 重置 constructor
let car4 = new MakeCarChild("benz", "400", "white", "run fast");

参考

蒋鹏飞: juejin.cn/post/684490…

原型链继承、构造函数继承、组合继承缺点 blog.csdn.net/wuchrStudy/…

继承演变过程 juejin.cn/post/711493…

ES6继承

ES6 的 class 作为寄生组合继承的语法糖

class MakeCar {
	constructor(price,color,performance){
			this.price = price
			this.color= color
			this.performance=performance
	}
	run(){
		console.log(console.log(this.performance))
	}
}

class MakeCarChild extends MakeCar{
    constructor(brand,...args){
        super(brand,...args);
        this.brand= brand;
    }
}

let car4= new MakeCarChild("benz","400","white","run fast")

Class 可以通过extends关键字实现继承。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

注意
ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。
ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。