javascript - 通过原型(prototype)继承扩展ES2015

标签 javascript oop ecmascript-6

我正在创建一个库,我想在其中提供一个帮助器来扩展基类,以便用户即使自己不使用 ES2015 也可以扩展它。问题是,如果基类恰好在 ES2015 中(因为它不是通过转译器发送),我从子类调用父构造函数会失败:

Class constructor Foo cannot be invoked without '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只是标准原型(prototype)继承之上的一个糖,但看起来你不能模拟它?还有另一种方法可以在运行时定义子类吗?

最佳答案

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

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

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

不过我还要注意,这也忽略了 ES6 中的另一个新功能,即 new.target。您还需要通过执行以下操作来保留它

constructor = function () {
  return Reflect.construct(currentClass, arguments, new.target);
};

确保事物的行为方式与类语法相同。

另请注意,您不得在此函数内使用thisReflect.construct 的返回值是新实例,因此如果您想在自己的自定义构造函数中使用它,您需要这样做

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

  _this.foo = "foo";
  return _this;
};

但是,如果你仔细想想,这本质上和做事情是一样的

constructor = class extends currentClass {}

关于javascript - 通过原型(prototype)继承扩展ES2015,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58050619/

相关文章:

javascript - React - 一种统一的方式,如果许多组件在生命周期方法中具有相同的代码段

javascript - 使用选定的单选按钮在页面加载时呈现输入

javascript - jQuery datepicker maxDate 问题

c++ - Arduino oop 错误

javascript - 移动和扩展图像以填充视口(viewport)过渡

javascript - 如何在 vb.net Sub 的末尾调用 javascript 函数?

c++ - 命令提示符中的字符 '<'

ruby - 在实例化时将类转换为子类

javascript - 覆盖一个setter,getter也必须被覆盖

javascript - 我可以在 Adob​​e Animate CC 中使用哪个 ECMAScript 版本