「这是我参与11月更文挑战的第27天,活动详情查看:2021最后一次更文挑战」
上篇文章简单说了原型继承、原型链继承,本篇文章将进行下扩展,说下剩余的几种继承方式:
父类属性:
function Animal(name){
//属性
this.name = name
//实例方法
this.call=function(call){
console.log(this.name + 'call'+'叫')
}
}
//原型方法
Animal.prototype.eat = function(food){
console.log(this.name + '吃' + food);
}
构造函数继承:
function Cat(name){
Anminal.call(this);
this.name = name;
}
let cat = new Cat();
实现思路:可以用.call()和.apply()将父类构造函数引入子类函数
优点:
1、 解决了子类构造函数向父类构造函数中传递参数问题
2、 可以实现多继承
缺点:
1、因为方法都在构造函数中定义,所以无法实现构造函数复用,每次使用都需要重新调用
2、不能继承原型属性/方法,只能继承父类的实例属性和方法
组合继承:
function Animal(name,call){
this.name = name
this.call = call
}
Animal.prototype.eat = function(){
return this.name + this.call + '叫'
}
function Cat(name,call){
Animal.call(this,name,call)
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
let cat = new Cat('咪咪','喵喵');
cat.eat();
实现思路:组合原型链继承和构造函数继承方式,调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用
优点:
1、 可以继承父类原型上的属性,还可以可以继承原型的属性和方法
2、 可以传参,函数可以复用
3、 不存在引用属性问题
缺点:
1、调用了两次父类构造函数,会有两份实例
寄生继承:
function Animal(type){
let obj = Object.create(type);
obj.eat = '鱼';
return obj;
}
var Cat = {
name:'咪咪',
call:'喵喵'
}
let cat = Animal(Cat);
实现思路:寄生是指函数内返回对象然后调用,创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回对象
优点:
1、解决了了组合继承中构造函数调用了两次父类构造函数的问题
缺点:
1、没用到原型,无法复用
寄生组合继承:
//父类函数
function Animal(name,call){
this.name = name
this.call = call
}
//父类方法
Animal.prototype.eat = function(){
return this.name + this.call + '叫'
}
//子类
function Cat(name,call){
//继承父类属性
Animal.call(this,name,call)
}
//继承父类方法
(function(){
let Dog = function(){};
Dog.prototype = Animal.prototype;
//父类的实例作为子类的原型
Cat.prototype = new Dog();
})();
//修复构造函数指向问题
Cat.prototype.constructor = Cat;
let cat = new Cat();
实现思路:寄生是指函数内返回对象然后调用,组合是在函数中用apply或者call方法引入另一个构造函数,可传参,函数的原型等于另一个实例。寄生组合是通过寄生的方式来修复组合式继承的不足
优点:
具备组合继承的一些优点,同时修复了组合继承调用了两次父类构造函数,会有两份实例的问题