Javascript 通过原型继承扩展ES2015

Javascript 通过原型继承扩展ES2015,javascript,oop,ecmascript-6,Javascript,Oop,Ecmascript 6,我正在制作一个库,在这里我想提供一个助手来扩展基类,这样即使用户自己不使用ES2015,也可以扩展它。问题是,如果基类恰好位于ES2015中(因为它不是通过transpiler发送的),则我从子类调用父构造函数失败,原因是: 类构造函数Foo不能在没有“new”的情况下调用 我正在努力实现的示例: class Foo { constructor() { console.log("In Foo"); } superMethod() { return console.l

我正在制作一个库,在这里我想提供一个助手来扩展基类,这样即使用户自己不使用ES2015,也可以扩展它。问题是,如果基类恰好位于ES2015中(因为它不是通过transpiler发送的),则我从子类调用父构造函数失败,原因是:

类构造函数Foo不能在没有“new”的情况下调用

我正在努力实现的示例:

class Foo {
  constructor() {
    console.log("In Foo");
  }

  superMethod() {
    return console.log("In super method");
  }

  static classMethod() {
    return console.log("In class method");
  }
}

Foo.extendClass = function (constructor, methods) {
  const currentClass = this;
  if (typeof constructor !== 'function') {
    methods = constructor;
    constructor = function () {
      return Object.getPrototypeOf(constructor).apply(this, arguments);
    };
  }
  constructor.prototype = Object.create(currentClass.prototype, {
    constructor: {
      value: constructor,
      writable: true,
      configurable: true
    }
  });
  Object.setPrototypeOf(constructor, currentClass);
  Object.assign(constructor.prototype, methods);
  return constructor;
};

const Bar = Foo.extendClass({
  subMethod: function() {
    return console.log("In sub method");
  }
});

b = new Bar();
问题出在这一行:

return Object.getPrototypeOf(constructor).apply(this, arguments);

那么我如何调用父级的构造函数呢?我原以为ES2015只是标准原型继承之上的一块糖,但看起来你无法模拟它?在运行时定义子类还有其他方法吗?

ES6在
[[Call]]
[[Construct]]
操作之间建立了更清晰的区别。ES6类只能使用
[[Construct]]
操作构造,但是
.call
/
.apply
[[call]]
操作。要使用
[[Construct]]
,您需要使用
Reflect.Construct()
来创建新实例。e、 g

constructor = function () {
  return Reflect.construct(Object.getPrototypeOf(constructor), arguments);
};

不过,我还要注意,这也忽略了ES6中的另一个新特性,即
new.target
。你也会希望通过这样做来保持这一点

constructor = function () {
  return Reflect.construct(currentClass, arguments, new.target);
};
以确保这些东西的行为方式与类语法相同

还请注意,您不得在此函数中使用此。它是新实例的
Reflect.construct
的返回值,因此如果您想在自己的自定义构造函数中使用它,您需要执行以下操作

constructor = function () {
  const _this = Reflect.construct(currentClass, arguments, new.target);

  _this.foo = "foo";
  return _this;
};
然而,如果你想一想,这基本上和你所做的是一样的

constructor = class extends currentClass {}

谢谢这是一个惊人的答案!
constructor = class extends currentClass {}