4.继承的方式

2020-07-03  本文已影响0人  原来哥哥是万家灯火

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('男', '医生');

优点:既不会重复调用父构造函数,也不会打乱原型链

上一篇 下一篇

猜你喜欢

热点阅读