放弃死记硬背,一步一步理解继承。
一、构造器继承
最简单的一种,继承构造器属性:
function Parent() {
this.name = 'Parent';
}
function Child() {
Parent.call(this);
this.age = 12;
}
这个方法是很简单,但是很明显只能继承构造器属性,那么原型属性想继承怎么办呢?
二、原型链继承
function Parent() {
this.name = 'Parent';
}
function Child() {
this.age = 12;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child
这种继承的问题有两个:1. 不能向父类构造函数传入参数;2. 所有子类函数继承同一父类的实例,子类修改了父类构造属性会互相影响。
三、组合继承
function Parent() {
this.name = 'Parent';
}
function Child() {
Parent.call(this);
this.age = 12;
}
Child.prototype = Parent.prototype;
Child.prototype.constructor = Child
这个继承方式看似没啥问题。但是直接让Child的原型等于Parent的原型会导致修改了子类的原型属性也会影响父类的原型。
四、优化组合继承
function Parent() {
this.name = 'Parent';
}
function Child() {
Parent.call(this);
this.age = 12;
}
Child.prototype = new Parent();
Child.prototype.constructor = Child
该方法其实已经没太大的问题了,也很简单。但是仍有一些不完美的地方,就是构造器属性定义了两遍,消耗没必要的内存。
五、寄生组合继承
function Parent() {
this.name = 'Parent';
}
function Child() {
Parent.call(this);
this.age = 12;
}
function F() {}
F.prototype = Parent.prototype;
Child.prototype = new F();
Child.prototype.constructor = Child
是不是解决了上面说的所有问题呢。这种继承还有一种简单的写法,借用ES6的语法。
function Parent() {
this.name = 'Parent';
}
function Child() {
Parent.call(this);
this.age = 12;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child