Динамическое расширение класса в javascript - PullRequest
0 голосов
/ 13 апреля 2020

Как мы можем динамически / программно расширять класс 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;
  }
}

?

Ответы [ 2 ]

1 голос
/ 13 апреля 2020

После некоторого взлома я обнаружил, что это ужасно работает.

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;
    });
1 голос
/ 13 апреля 2020

Здесь есть три проблемы:

(1) super доступен только внутри методов объекта, поэтому нет доступа к super в функции стрелки. Это нужно каким-то образом заменить обычным вызовом функции.

(2) Классы могут только создаваться, но не вызываться (в отличие от функций, действующих как конструкторы). Поэтому вы не можете просто .call конструктор классов на экземпляр "подкласса". Вы должны создать экземпляр суперкласса и скопировать его в подкласс, в конечном итоге потеряв геттеры / сеттеры.

(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?

...