【编程向导】JavaScript-继承-寄生式与组合式继承

寄生组合式继承

寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。 本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

🌰 示例:

function inherit(child, parent) {
  // 创建对象
  let prototype = Object.create(parent.prototype);

  // 增强对象
  prototype.constructor = child;

  // 指定对象
  child.prototype = prototype;
}

这个示例中的函数实现了寄生组合式继承的最简单形式。这个函数接收两个参数:子类型构造函数超类型构造函数。

  • 第一步是创建超类型原型的一个副本
  • 第二步是为创建的副本添加 constructor 属性,从而弥补因重写原型而失去的默认的 constructor 属性
  • 最后一步,将新创建的对象(即副本)赋值给子类型的原型
function inherit(children, parent) {
  // 创建对象
  let prototype = Object.create(parent.prototype);
  // 增强对象
  prototype.constructor = children;
  // 指定对象
  children.prototype = prototype;
}

function Parent(name) {
  this.name = name;
  this.num = [0, 1, 2];
}

Parent.prototype.sayName = function() {
  alert(this.name);
};

function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}

inherit(Child, Parent);

Child.prototype.sayAge = function() {
  console.log(this.age);
};

解决两次调用的方法是使用寄生组合式继承。

寄生组合式继承与组合继承相似,都是通过借用构造函数来继承不可共享的属性,通过原型链的混成形式来继承方法和可共享的属性。只不过把原型继承的形式变成了寄生式继承。

使用寄生组合式继承可以不必为了指定子类型的原型而调用父类型的构造函数,从而寄生式继承只继承了父类型的原型属性,而父类型的实例属性是通过借用构造函数的方式来得到的。

下方中会对寄生继承进行详细说明:

function Parent(name) {
  this.name = name;
  this.num = [0, 1, 2];
}

Parent.prototype.sayName = function() {
  return this.name;
};

function Child(name, age) {
  Parent.call(this, name);
  this.age = age;
}

Child.prototype = Object.create(Parent.prototype);

Child.prototype.constructor = Child;

// The first instance
const boy = new Child('Jothan', 22);

boy.num.push(3);
console.log(boy.num);
// [0, 1, 2, 3]

boy.sayName();
// 'Jothan'

// The second instance
const girl = new Child('Kat', 18);

console.log(girl.num);
// [0, 1, 2]

girl.sayName();
// 'Kat'

这个例子的高效率体现在它只调用了一次 Parent 构造函数,并且因此避免了在 Child.prototype 上面创建不必要的、多余的属性。与此同时,原型链还保持不变。

寄生式继承

寄生式继承(Parasitic Inheritance):创建一个仅用于封装继承过程的函数,在函数内部以某种方式增强对象

function creator(origin) {
  // 以 origin 为原型对象创建一个新对象
  let clone = Object.create(origin);

  // 以某种方式来增强这个对象
  clone.sayHi = function () {
    console.log('Hello world!');
  };

  // 返回这个对象
  return clone;
}

let friendship = {
  name: 'Uzi',
  friends: ['Amy', 'Ben', 'Tom'],
};

// 具有实例的原型person的所有属性和方法,也有自己的方法
let uzi = creator(friendship);

uzi.sayHi();
// Hello world!

在主要考虑对象而 不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。前面示范继承模式时使用的 Object 函数不是必需的,任何能够返回新对象的函数都适用于此模式。

⚠️ 注意: 使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率;这一点与借用构造函数模式类似。

  • 12
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wtrees_松阳

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值