【问题标题】:Dynamically extending a class in javascript在javascript中动态扩展一个类
【发布时间】:2020-04-12 22:12:18
【问题描述】:

我们如何动态/以编程方式扩展 javascript 类?

更具体地说,给定类似

class Polygon {
  constructor(area, sides) {
    this.area = area;
    this.sides = sides;
  }
}

const Rectangle = extend(Polygon, (length, width) => {
  super(length * width, 4);
  this.length = length;
  this.width = width;
});

我们如何实现类似extend 的东西,使其行为与

class Rectangle extends Polygon {
  constructor(length, width) {
    super(length * width, 4);
    this.length = length;
    this.width = width;
  }
}

?

【问题讨论】:

标签: javascript class inheritance prototypal-inheritance


【解决方案1】:

这里有三个问题:

(1) super 只能在对象方法中使用,因此无法在箭头函数中访问 super。这需要以某种方式替换为常规函数调用。

(2) 类只能被构造,不能被调用(与充当构造函数的函数不同)。因此,您不能只是 .call 将类构造函数添加到“子类”实例上。您必须创建超类的实例并将其复制到子类中,最终失去 getter / setter。

(3) 箭头函数有一个词法this,因此您不能在箭头函数内使用this 访问实例。

鉴于这三个问题,一个可行的替代方案是:

  function extend(superclass, constructor) {
    function Extended(...args) {
      const _super = (...args) => Object.assign(this, new superclass(...args));
      constructor.call(this, _super, ...args);
    }
    Object.setPrototypeOf(Extended, superclass);
    Object.setPrototypeOf(Extended.prototype, superclass.prototype);
    return Extended;
 }

  const Rectangle = extend(Polygon, function(_super, length, width) {
     _super(/*...*/);
     /*...*/
  });

但老实说......原生class ... extends有什么问题?

【讨论】:

  • 感谢您提供的信息直截了当的回答。 class ... extends 显然是大多数时候要走的路,但我正在寻找一种能够基于某些输入数据以编程方式扩展类的解决方案。具体来说,我正在尝试通过扩展 HTMLElement 创建 Web 组件,但是您的解决方案似乎不适用于这种情况(new HTMLElement() 给出“TypeError:非法构造函数。”)。有什么建议可以让它发挥作用吗?
  • 因为HTMLElement 不是一个类,它是一个接口。使用实现它的类。
  • 喜欢这个jsfiddle.net/6kbnrwuL/1 ?我仍然看到同样的问题。
【解决方案2】:

经过一番修改后,我发现这非常有效。

function extend(superclass, construct) {
    return class extends superclass {
        constructor(...args) {
            let _super = (...args2) => {
                super(...args2)
                return this;
            };
            construct(_super, ...args);
        }
    };
}

const Rectangle = extend(Polygon, function(_super, length, width) {
         let _this = _super(length * width, 4);
         _this.length = length;
         _this.width = width;
    });

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2012-11-11
  • 1970-01-01
  • 2020-10-01
  • 2013-04-27
  • 2010-12-05
  • 1970-01-01
  • 2018-01-15
相关资源
最近更新 更多