引言:前端小白一枚,此文集用于个人前端知识点总结,记录实际项目开发过程中踩过的抗。
一点一滴,汇聚成河!
JS常用继承方式:原型链继承、构造函数继承、组合继承。
1、原型链继承
实现原理:使子类的原型对象指向父类的实例。
function Parent(){
this.color=[“red”,”blue”,”green”];
}
Parent.prototype.getColor=function(){
return console.log(this.color);
}
function Child(){
this.subColor=[“red”];
}
Child.prototype=new Parent(); //子类的原型对象指向父类的实例
// 给子类添加特有的方法,注意顺序要在继承之后
Child.prototype.getsubColor=function() {
return console.log(this.subColor);
}
缺点:构造函数原型上的属性在所有构造函数的实例中是共享的,即属性没有私有化,原型上属性的改变会作用到所有的实例上。
2、借用构造函数继承
实现原理:在构造子类构造函数时,内部使用call或apply来调用父类的构造函数,使得父类构造函数的this将指向子类构造函数的实例
function Parent(){
this.colors=[“red”];
}
Parent.prototype.getColor=function(){
return console.log(“这里是父类原型链”);
}
function Child(){
Parent.call(this); //继承Parent
}
优缺:实现了属性的私有化。将Parent函数在Child构造函数中调用,在每个实例中执行,这样每个实例中都会有一份Parent构造函数中属性和方法的副本,也就实现了继承Parent。避免了原型链继承中,原型属性共享的问题。
缺点:子类无法访问父类原型链上的属性。所有的方法都需要在构造函数中定义,这样函数复用就无从谈起了。
3、组合继承(JS中最常用的继承模式)
实现原理:原型链 + 构造函数
function Parent(name){
this.name=name;
this.color=[“red”];
}
Parent.prototype.sayName=function(){
console.log(this.name);
}
function Child(name,age){
Parent.call(this,name); // 继承构造函数内的
this.age=age;
}
// 继承原型链上的
Child.prototype=new Parent(); // 优化 :Child.prototype=Object.create( Parent.prototype )
Child.prototype.constructor=Child; //construtor指向原型对应的构造函数
Child.prototype.sayAge=function(){
console.log(this.age);
}
【注】Child.prototype = new Parent(); 会导致Child.prototype的constructor指向Parent;然而constructor的定义是要指向原型属性对应的构造函数的。Child.prototype是Child构造函数的原型,所以应该添加一句纠正:Child.prototype.constructor = Child;
优点:使用原型链实现对属性和方法的继承,而通过构造函数实现对实例属性的继承。
缺点:父类构造函数执行了两次(优化Child.prototype=Parent.prototype);无法区分实例是由父类还是子类创建(优化: Child.prototype=Object.create( Parent.prototype ) ,使父子类原型对象隔离)