原型链继承
// 1 用父类构造函数构建一个父类空对象
// 2 将子类构造函数的prototype指向新建的对象
// 3 添加子类特有的方法
function SuperType(){
this.property = true
}
SuperType.prototype.getSuperValue = function(){
return this.property
}
function SubType(){
this.subproperty = false
}
SubType.prototype = new SuperType() //构建prototype
SubType.prototype.getSubValue = function(){
return this.subproperty
}
缺陷:
1 若父类对象包含引用类型数据,该数据会被所有子类对象共享
//关于父类对象包含引用类型数据的测试
function SuperType(){
this.arr = ['1', '2', '3']
}
SuperType.prototype.changeArr = function(char){
this.arr.push(char)
}
function SubType(){
}
SubType.prototype = new SuperType()
SubType.prototype.getArr = function(){
console.log(this.arr)
}
const ins1 = new SubType()
const ins2 = new SubType()
ins1.changeArr('4')
ins2.getArr() //['1', '2', '3', '4']
2 创建子类对象时不能给父类构造函数传参
借用构造函数继承
// 通过call/apply方法在子类构造函数中调用父类构造函数
function SuperType(name){
this.name = name
}
function SubType(name, age){
SuperType.call(this, name)
this.age = age
}
缺陷:
父类方法无法重用,且定义在父类原型上的方法对子类不可见
组合继承
// 前面两种方法的结合,使用父类对象最为原型继承方法,使用父类构造函数获得数据
function SuperType(name){
this.name = name
this.arr = [1, 2, 3]
}
SuperType.prototype.sayName = function(){
console.log(this.name)
}
function SubType(name, age){
SubType.call(this, name)
this.age = age
}
SubType.prototype = new SuperType()
SubType.prototype.sayAge = function(){
console.log(this.age)
}
缺陷:
构建原型对象时多调用了一次父类构造函数,导致原型对象带上了无意义的父类数据
组合寄生式继承
// 使用空对象作为原型实现继承,避免了原型继承的缺陷
function object(target){
function temp(){}
temp.prototype = target
return new temp()
}
function inherit(subType, superType){
let prototype = object(superType.prototype)
prototype.construtor = subType
subType.prototype = prototype
}
function SuperType(name){
this.name = name
}
SuperType.prototype.sayName = function(){
console.log(this.name)
}
function SubType(name, age){
SuperType.call(this, name)
this.age = age
}
inherit(SubType, SuperType)
SubType.prototype.sayAge = function(){
console.log(this.age)
}