js实现多继承

395 阅读1分钟
/*保证typescript可以正确计算类型*/
export function extend<T, U>(target: Type<T>, source1: Type<U>): Type<T & U>;
export function extend<T, U, V>(
  target: Type<T>,
  source1: Type<U>,
  source2: Type<V>
): Type<T & U & V>;
export function extend<T, U, V, W>(
  target: Type<T>,
  source1: Type<U>,
  source2: Type<V>,
  source3: Type<W>
): Type<T & U & V & W>;
export function extend<T, U, V, W, X>(
  target: Type<T>,
  source1: Type<U>,
  source2: Type<V>,
  source3: Type<W>,
  source4: Type<W>
): Type<T & U & V & W & X>;
/*结束*/


/*功能*/
export function extend(target: Type<any>, ...sources: Type<any>[]): Type<any> {
  return extend2(target)(...sources.reverse());
}

function extend2(target: Type<any>) {
  return (...sources: Type<any>[]): Type<any> => {
    let targetPrototype = target.prototype;
    // 继承
    (function() {
      // 创建一个干净的实例
      function beget() {
        var F = function() {
          // sources属性处理
          sources.map(source => source.call(this));
        };
        // sources处理
        assign(F.prototype, ...sources.map(source => source.prototype));
        return new F();
      }
      let prototype = beget();
      prototype.constructor = target;
      // 继承
      target.prototype = prototype;
      // 原来的方法
      assign(target.prototype, targetPrototype);
    })();
    return target as any;
  };
}
/*结束*/

测试

import { expect } from "chai";
import { extend } from "./extend";
export class A {
  title: string = "a";

  run() {
    return "a";
  }
}
export class B {
  title: string = "b";
  demo: string = "demo";

  add() {
    return "b";
  }
}
export class D {
  title: string = "d";
  console() {
    return "d";
  }
}

let C = extend(A, B, D);
const c = new C();

describe("extend", () => {
  it("c.demo", () => {
    expect(c.demo).equal("demo");
  });
  it("c.add", () => {
    expect(c.add()).equal("b");
  });
  it("c.add", () => {
    expect(c.run()).equal("a");
  });
  it("c.add", () => {
    expect(c.console()).equal("d");
  });
});