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");
参考
原型链继承、构造函数继承、组合继承缺点 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。