一、原型链继承
将父类的实例作为子类的原型。
function Animal (name) { //定义一个动物类
this.name = name; //属性
this.play= function(){ //方法
console.log(this.name + '正在玩耍');
}
}
Animal.prototype.eat = function(food) { //原型方法
console.log(this.name + '正在吃:' + food);
};
function Dog(){ //定义子类Dog
}
Dog.prototype = new Animal(); //父类的实例赋值给子类原型实现继承
Dog.prototype.name = 'dog';
优点:
1.简单,易于实现;
缺点:
1.在创建子类的实例时, 不能向父类传参;
2.来自原型对象的所有属性被所有实例共享;
3.不可以实现多继承;
二、构造函数继承
子类构造函数中调用父类的构造函数。
function Cat(name){ //定义子类Cat
Animal.call(this,name);
}
优点:
1.可以实现多继承(call多个父类对象);
2.创建子类的实例时,可以向父类传递参数;
缺点:
1.只能继承父类的实例属性和方法,不能继承原型属性/方法;
2.方法都在构造函数中定义,无法复用;
三、组合继承
子类构造函数中调用父类的构造函数,将父类的实例作为子类的原型。
function Duck(name){ //定义子类Duck
Animal.call(this,name);
}
Duck.prototype = new Animal();
优点:
1.解决原型链继承和构造函数继承的缺点,综合其优点;
缺点:
1.会调用两次父类的构造函数;
四、寄生组合继承
创建寄生类,原型指向父类原型,令子类原型等于寄生类实例。
通过寄生方式,砍掉父类的实例属性,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点。
function Fish(name){ //定义子类Fish
Animal.call(this,name);
}
function Super(){ //定义寄生类Super
}
Super.prototype = Animal.prototype;
Fish.prototype = new Super();
Fish.prototype.constructor = Fish; // 需要修复下构造函数
五、实例继承、拷贝继承
function A(name){
var instance = new Animal();
instance.name = name || 'Tom';
return instance;
}
function B(name){
var animal = new Animal();
for(var p in animal){
B.prototype[p] = animal[p];
}
B.prototype.name = name;
}
六、ES6 class语法糖
ES6继承的结果和寄生组合继承相似,本质上,ES6继承是一种语法糖。