1.原型链继承
function Parent(name,age){
this.name=name
this.age=age
}
function Son(favor,sex){
this.favor=favor
this.sex=sex
}
// 关键点
Son.prototype= new Parent("好好的",23)
Son.prototype.constructor = Son
let sonObj=new Son("篮球","男")
原型链继承的核心就是子类构造器的原型指向父类构造器的的实例,这样就可以通过原型链查找到父类实例的属性和方法,缺点就是不能通过子类构造器像父类构造器传递参数。
2.借用构造函数继承
function Parent (name, age) {
this.name = name
this.age = age
}
function Son (name, age, favor, sex) {
this.favor = favor
this.sex = sex
// 关键点
Parent.call(this, name, age)
}
let sonobj2 = new Son("lisi", 34, "打篮球", "男");
通过函数对象的call方法,可以实现子类构造函数向父类构造函数传递参数,缺点是没有继承父类原型的属性和方法,无法访问父类原型上的属性和方法。
3.组合模式(借用构造函数+原型链继承)
function People(name,sex,phone){
this.name=name
this.sex=sex
this.phone=phone
}
function ChinesePeople(name,sex,phone,national){
// 关键点
People.call(this, name, sex, phone) // 1
this.national=national
}
// 关键点
ChinesePeople.prototype= new People() // 2
ChinesePeople.prototype.constructor = ChinesePeople
let sonobj2 = new Son("lisi", 34, "打篮球", "男");
组合模式结合了前面两种的优点,可以向父类构造函数传递参数,也可以访问父类原型上的属性和方法。但是也带来了新的问题,调用了两次父类构造函数,调用构造函数带来问题:分配内存空间,浪费内存,且第二次调用赋值毫无意义。
4.寄生组合继承模式=借用构造函数继承+寄生继承。(最佳实践)
function People(name,sex,phone){
this.name=name
this.sex=sex
this.phone=phone
}
function ChinesePeople(name,sex,phone,national){
// 关键点
People.call(this, name, sex, phone)
this.national=national
}
// 关键点
ChinesePeople.prototype= Object.create(People.prototype)
ChinesePeople.prototype.constructor = ChinesePeople
let sonobj2 = new Son("lisi", 34, "打篮球", "男");
什么是寄生继承?,就是子类构造器的原型不再指向父类构造器的的实例,而是克隆一个对象,并让这个对象的_proto_指向父类构造器的原型对象。然后在让子类构造器的原型指向它。通过Object.create方法可以很好的实现。