Я бы хотел использовать конструктор класса ES6 как миксин-функцию с двойным назначением.
У меня есть простой класс с несколькими методами.Упрощенный пример:
class foo {
constructor() {}
hi() { console.log('hello'); }
}
В большинстве случаев я создаю экземпляры этого класса:
let bar = new foo();
bar.hi(); // hello
Иногда он используется в качестве суперкласса:
class baz extends foo {
constructor() { super(); }
}
let bar = new baz();
bar.hi(); // hello
Но,поскольку методы могут работать независимо от чего-либо еще, было бы неплохо, если бы я мог использовать конструктор в качестве миксина, например так:
class foo {
constructor( mixin ) {
if ( !new.target ) { // not called with `new`
if ( !mixin ) throw new TypeError( 'Must supply mixin' );
mixin.hi = foo.prototype.hi;
return mixin;
}
}
// ...
}
let bar = {}; // this could be instance of another class, whatever.
foo( bar ); // Class constructor foo cannot be invoked without 'new'
bar.hi();
Это проблема, с которой я столкнулся.Конструкторы не могут быть вызваны, как если бы они были просто нормальной функцией.
Есть ли какой-нибудь способ не дать конструктору выдать ошибку при вызове без new
, не возвращаясь к подходу ES5 построения классов?
Я попытался обернуть класс в обычную функцию и использовать new.target
(мой env - ES6), чтобы определить, когда используется new
:
function Goo( mixin ) {
if ( new.target ) return new foo();
if ( !mixin ) throw new TypeError( 'Must supply mixin' );
mixin.hi = foo.prototype.hi;
return mixin;
}
let goo = new Goo(); // I get a new instance of foo
goo.hi(); // hello
let bar = {};
Goo( bar );
bar.hi(); // hello
... нобыстро понял, что:
class oof extends Goo { // ugh
Кроме того, мне пришлось бы клонировать static
материал с foo
на Goo
, то есть Мех.
Как запасной вариант я в настоящее времяиспользуйте статический метод mixin()
в классе foo
:
class foo {
static mixin( target ) {
if ( !target ) throw new TypeError( 'Must supply target' );
target.hi = foo.prototype.hi;
return target;
}
// ...
}
let bar = {};
foo.mixin( bar ); // Well, it's semantic at least
bar.hi(); // hello
Но я заинтересован, даже чтобы посмотреть, можно ли это сделать, чтобы что-то работало в этих трех сценариях:
let ifoo = new foo();
ifoo.hi();
class woo extends foo { /* ... */ }
let iwoo = new woo();
iwoo.hi();
let bar = {};
let ibar = foo( bar );
ibar.hi();
Кто-нибудь хочет узнать, выполнимо ли это, даже если это, вероятно, не следует делать?