1 原型链继承
核心:让子类的原型指向父类的实例
ChildType.prototype = new ParentType() // 所有涉及到原型链继承的继承方式都要修改子类构造函数的指向,否则子类实例的构造函数会指向PerentType。 ChildType.prototype.constructor =ChildType;
优点:父类方法可以复用
缺点:
- 父类的引用属性会被所有子类实例共享
- 子类构建实例时不能向父类传递参数
2 .构造函数继承
核心:将父类构造函数的内容复制给了子类的构造函数。这是所有继承中唯一一个不涉及到prototype的继承。
ParentType.call(ChildType);
优点:和原型链继承完全反过来。
- 父类的引用属性不会被共享
- 子类构建实例时可以向父类传递参数
缺点:父类的方法不能复用,子类实例的方法每次都是单独创建的。
3 .组合继承
核心:原型式继承和构造函数继承的组合,兼具了二者的优点。
function ParentType() { this.name = 'parent'; this.arr = [1, 2, 3]; } ParentType.prototype.say = function() { console.log('this is parent') } function ChildType() { ParentType.call(this) // 第二次调用ParentType } ChildType.prototype = new ParentType() // 第一次调用ParentType
优点:
- 父类的方法可以被复用
- 父类的引用属性不会被共享
- 子类构建实例时可以向父类传递参数
缺点:
调用了两次父类的构造函数,第一次给子类的原型添加了父类的name, arr属性,第二次又给子类的构造函数添加了父类的name, arr属性,从而覆盖了子类原型中的同名参数。这种被覆盖的情况造成了性能上的浪费。