1.原型链继承
function Parent(name,age){
this.colors=['blue','green','red'];
}
Parent.prototype.getColors=function(){
return this.colors;
}
function Child(){};
Child.prototype=new Parent();
var child1=new Child();
child1.colors.push('yellow');
var child2=new Child();
console.log(child2.colors); // blue,green,red,yellow
优点: 可以继承构造函数和原型上的属性和方法。
问题:
- 原型链中包含的引用数值类型被所有实例共享
- 子类在实例化的时候不能给父类构造函数传递参数。
2.构造函数继承
function Super1Type(name) {
this.name = name;
}
function Sub1Type() {
Super1Type.call(this, 'shuaina');
this.age = 25;
}
let instances = new Sub1Type();
console.log(instances.name);
借用构造函数实现继承解决了原型链继承的 2 个问题:引用类型共享问题以及传参问题。但是由于方法必须定义在构造函数中,所以会导致每次创建子类实例都会创建一遍方法。
3.组合继承
function Animal(name){
this.name=name;
this.colors=['red','blue','green'];
}
Animal.prototype.getName=function(){
return this.name;
}
function Dog(name,age){
Animal.call(this,name);
this.age=age;
}
Dog.prototype=new Animal();
var dog1=new Dog('shuai',25);
dog1.colors.push('white');
var dog2=new Dog('wang',18);
console.log(dog2);
组合继承结合了原型链和盗用构造函数,将两者的优点集中了起来。基本的思路是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。这样既可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。 问题:调用了两次构造函数
4.寄生式组合继承
组合继承已经相对完善了,但还是存在问题,它的问题就是调用了 2 次父类构造函数,第一次是在 new Animal(),第二次是在 Animal.call() 这里。 所以解决方案就是不直接调用父类构造函数给子类原型赋值,而是通过创建空函数 F 获取父类原型的副本。
function object(o){
function F(){};
F.prototype=o;
return new F();
}
function inheritPrototype(child,parent){
let prototype=object(parent.prototype);
prototype.constructor=child;
child.prototype=prototype;
}
function Animal(name){
this.name=name;
this.colors=['red','blue','green'];
}
Animal.prototype.getName=function(){
return this.name;
}
function Dog(name,age){
Animal.call(this,name);
this.age=age;
}
var dog1=new Dog('shuai',25);
dog1.colors.push('white');
var dog2=new Dog('wang',18);
console.log(dog2);
5.class实现继承
class Animal{
constructor(name){
this.name=name;
}
getName(){
return this.name;
}
}
class Dog extends Animal{
constructor(name,age){
super(name);
this.age=age;
}
}