一、 简单原型继承
function Parent() {
this.a = 1;
this.b = [1];
}
Parent.prototype.hello = function() {}
function Child(name) {
this.name = name;
}
Child.prototype = new Parent(); // 核心
Child.prototype.constructor = Child; // 修正Child的构造函数
let child1 = new Child("child1");
let child2 = new Child("child2");
核心:使用父类的实例来作为子类的原型对象
缺点:1.父类的引用属性会在子类实例中共享 2.创建子类实例时无法给父类构造函数传参
二、 借用构造函数
function Parent(num) {
this.a = num;
this.b = [1];
this.hello2 = function() {} // 此函数会被复制到子类
}
Parent.prototype.hello = function() {} // 此函数不会被复制到子类
function Child(name, num) {
Parent.call(this, num); // 核心
this.name = name;
}
let child1 = new Child("child1", 1);
let child2 = new Child("child2", 2);
核心:借用父类的构造函数,将父类的属性复制给子类实例,没有用到原型
优点:解决了简单原型继承的两个问题
缺点:由于没有用到原型,父类复制来的函数无法实现复用
三、 组合继承
function Parent(num) {
this.a = num;
this.b = [1];
}
Parent.prototype.hello = function() {}
function Child(name, num) {
Parent.call(this, num); // 核心
this.name = name;
}
Child.prototype = new Parent(); // 核心,此处实例化了一个多余的父类对象
Child.prototype.constructor = Child; // 修正Child的构造函数
let child1 = new Child("child1", 1);
let child2 = new Child("child2", 2);
核心:将上述两种方式组合起来使用,将需要复用的函数都放在原型上,将需要复制的属性通过借用构造函数复制给子类实例
优点:解决了所有问题
缺点:实例化了一个“多余”的父类对象
四、 寄生组合继承
function Parent(num) {
this.a = num;
this.b = [1];
}
Parent.prototype.hello = function() {}
function Child(name, num) {
Parent.call(this, num); // 核心
this.name = name;
}
function extend(child, parent) {
let F = function() {};
F.prototype = parent.prototype;
child.prototype = new F(); // 核心,用一个空函数来避免实例化属性的浪费
child.prototype.constructor = child; // 修正构造函数
}
extend(Child, Parent); // 核心
let child1 = new Child("child1", 1);
let child2 = new Child("child2", 2);
核心:与组合继承基本一样,只是针对多余的实例化进行了优化
优点:解决了所有问题
缺点:比较麻烦……