Javascript实现多类继承

好像在Javascript中多继承出现的场景并不多,这是因为在es6中并没有显式的支持多继承,不过,如果你认为它不能做到多继承就错了。

比如有类A、B、C、D,我希望类A去继承B、C、D,那么,可以让B去继承C,C继承D,最后让A继承B,就实现了多继承的效果。

在es6中,通过extends关键字去实现继承,如下示例。

class B extends C {}
class C extends D {}

但是,这样一层一层的去写也太麻烦了,那么我们需要了解另一个原理。

extends关键字之后除了放一个类或构造函数,还可以是一个Javascript表达式,任何一个可以解析为类或构造函数的表达式都是有效的,它会在求值类定义时被求值。

我们把extends之后的class改为一个表达式如下。

class Parent {}
function getParentClass() {
  console.log('get parent class')
  return Parent;
}
class Child extends getParentClass() {}

所以上述代码片段在控制台打印了get parent class

基于这个特性,上面B、C、D三个类可以通过混入类的方式来实现效果。我们实现一个混入类的函数,该函数接收一个类作为参数,在函数内部去继承这个传入的类。

function Parent() {
  console.log('parent')
}
const ParentMixin = (SuperClass) => class extends SuperClass {
  parentLog() {
    console.log('parent log')
  }
}

const ChildMixin = (SuperClass) => class extends SuperClass {
  childLog() {
    console.log('child log')
  }
}

const SubChildMixin = (SuperClass) => class extends SuperClass {
  subChildLog() {
    console.log('subchild log')
  }
}

class Base extends SubChildMixin(ChildMixin(ParentMixin(Parent))) {}

const instance = new Base(); // parent
instance.subChildLog() // subchild log
instance.childLog() // child log
instance.parentLog() // parent log

这样写的话代码层层套娃不够简单优雅,实现一个辅助pipe函数,将函数的嵌套展开。

const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);

class Base extends pipe(SubChildMixin, ChildMixin, ParentMixin)(Parent) {}

总结

js多继承的使用场景并不是很多,甚至很多地方已经不建议使用多继承的方式,但是并不妨碍我们了解它的实现原理。

本文完。😊

如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注