1.原型链继承
function Human(gender) {
this.gender = gender;
this.friends = [];
}
Human.prototype.run = function () {
console.log('i am running')
}
function Adult(profession) {
this.profession = profession;
}
Adult.prototype = new Human('男');
let xiaoWang = new Adult('医生');
缺点:
(1)创建子类实例时,无法指定父类构造函数的参数。即不能:
let xiaoWang = new Adult('男', '医生');
(2)因为继承的属性和方法都在实例的原型上,adult.__proto = human,所以一个实例的更改属性可能会影响到其他实例。为什么是可能的原因在创建对象之原型模式已解释过。
2.构造函数继承:
function Human(gender) {
this.gender = gender;
this.run = function () {
console.log('i am running')
}
}
function Adult(gender, profession) {
Human.apply(this, [gender]);
this.profession = profession;
}
let xw = new Adult('男', '医生');
缺点:所有的方法都需要重新创建一遍,浪费内存
3.组合继承
function Human(gender) {
this.gender = gender;
}
Human.prototype.run = function () {
console.log('i am running')
}
function Adult(gender, profession) {
Human.apply(this, [gender]);
this.profession = profession;
}
Adult.prototype = new Human();
Adult.prototype.constructor = Adult;
let xw = new Adult('男', '医生');
这是最常用的继承方式,不过也还有小缺陷:Human函数会被调用两次。
4.原型式继承,就是对Object.create的模拟实现,将传入的参数作为创建的对象的原型
function create(o) {
function F() {}
F.prototype = o;
return new F();
}
let man = {gender: '男'};
let xw = create(man);
let xl = create(man);
xw.profession = '医生';
xl.profession = '记者';
缺点:属性、方法都共享
5.寄生式继承,就是原型式继承时,拓展一些属性、方法
function create(o) {
let obj = Object.create(o);
obj.profession = '医生';
obj.operating = function() {
console.log('我正给病人做手术')
}
}
let man = {gender: '男'};
let xw = create(man);
缺点:和构造函数一样,同样存在浪费内存
6.寄生组合模式
先回顾一下组合模式:
function Human(gender) {
this.gender = gender;
}
Human.prototype.run = function () {
console.log('i am running')
}
function Adult(gender, profession) {
Human.apply(this, [gender]);
this.profession = profession;
}
Adult.prototype = new Human();
Adult.prototype.constructor = Adult;
let xw = new Adult('男', '医生');
组合模式中,通过Human.apply(this, [gender]),adult已经可以拥有human中不在Human.prototype上的属性和方法,如gender。接下来只需要使adult拥有Human.prototype上的属性和方法即可,为了达到这个目的才有了下面这一句:
Adult.prototype = new Human();
但这有个缺点,就是为了得到一个adult,Human函数会被调用两次。可以想象,如果Human还以这种方式继承了Animal的话,那Animal会被调用3次。
所以不妨这样:
Adult.prototype = Human.prototype;
现在adult可以拥有Human.prototype上的方法了,但是又有点小瑕疵:
访问 adult.constructor 得到的是 Human。在原型链上就少了Adult这一环,这显得不合理
所以寄生组合模式来了:
function Human(gender) {
this.gender = gender;
}
Human.prototype.run = function () {
console.log('i am running')
}
function Adult(gender, profession) {
Human.apply(this, [gender]);
this.profession = profession;
}
function F() {}
F.prototype = Human.prototype;
Adult.prototype = new F();
Adult.prototype.constructor = Adult;
let xw = new Adult('男', '医生');
优点:既不会重复调用父构造函数,也不会打乱原型链
网友评论