Javascript 有没有一种方法可以让类构造函数像调用普通函数一样被调用?

Javascript 有没有一种方法可以让类构造函数像调用普通函数一样被调用?,javascript,ecmascript-6,new-operator,mixins,es6-class,Javascript,Ecmascript 6,New Operator,Mixins,Es6 Class,我想将一个ES6类构造函数作为一个混合函数来使用 我有一个简单的类和一些方法。一个简化的例子: class-foo{ 构造函数(){} hi(){console.log('hello');} } 在大多数情况下,我创建此类的实例: let bar=new foo(); bar.hi();//你好 有时它被用作超类: 类baz扩展了foo{ 构造函数(){super();} } 设bar=new baz(); bar.hi();//你好 但是,由于这些方法可以独立于任何其他方法工作,如果我可

我想将一个ES6类构造函数作为一个混合函数来使用

我有一个简单的类和一些方法。一个简化的例子:

class-foo{
构造函数(){}
hi(){console.log('hello');}
}
在大多数情况下,我创建此类的实例:

let bar=new foo();
bar.hi();//你好
有时它被用作超类:

类baz扩展了foo{
构造函数(){super();}
}
设bar=new baz();
bar.hi();//你好
但是,由于这些方法可以独立于任何其他方法工作,如果我可以将构造函数用作mixin,那就太好了,如下所示:

class-foo{
构造函数(mixin){
如果(!new.target){//未使用'new'调用`
如果(!mixin)抛出新类型错误('Must supply mixin');
mixin.hi=foo.prototype.hi;
返混;
}
}
// ...
}
设bar={};//这可能是另一个类的实例,不管怎样。
富(酒吧);//类构造函数foo不能在没有“new”的情况下调用
bar.hi();
这就是我遇到的问题。不能像调用普通函数一样调用构造函数

当调用构造函数时,如果没有
new
,没有返回到ES5方法构建类,是否有任何方法可以阻止构造函数抛出错误

我尝试用普通函数包装该类,并使用
new.target
(我的环境是ES6)检测何时使用
new

函数Goo(mixin){
if(new.target)返回新的foo();
如果(!mixin)抛出新类型错误('Must supply mixin');
mixin.hi=foo.prototype.hi;
返混;
}
设goo=new goo();//我得到了一个新的foo实例
goo.hi();//你好
设bar={};
古(巴);
bar.hi();//你好
……但很快意识到:

类oof扩展了Goo{//ugh
另外,我必须将
静态
东西从
foo
克隆到
Goo
,这就是meh

作为备用方法,我目前在
foo
类上使用静态
mixin()
方法:

class-foo{
静态混合(目标){
如果(!target)抛出新的TypeError('Must supply target');
target.hi=foo.prototype.hi;
回报目标;
}
// ...
}
设bar={};
foo.mixin(bar);//嗯,至少是语义上的
bar.hi();//你好
但我很渴望,甚至只是想看看是否可以做到,在这三种情况下都能做到:

让ifoo=newfoo();
ifoo.hi();
类woo扩展了foo{/*…*/}
让iwoo=新woo();
你好;
设bar={};
设ibar=foo(bar);
ibar.hi();
有人想看看它是否可以做,即使它可能不应该做?

基于,我提出了以下函数:
altEgo()

它创建一个
mask
函数,函数后面有
alt
(用于正常调用)和
ego
(用于
new
实例)。它检查
new.target
以决定是使用
alt()
还是
new ego()
。您还可以
扩展
mask
mask

//要向fooFn添加另一个自我:
//fooFn=altEgo(altFn,fooFn);
功能altEgo(alt,ego){
如果(typeof alt!==“function”)抛出新的TypeError(`alt必须是一个函数`);
如果(自我的类型!=“函数”)抛出新的类型错误(“自我必须是函数”);
常量掩码=函数(…参数){
return new.target?Reflect.construct(自我,args,new.target):alt(自我,面具,…args);
}
for(Object.getOwnPropertyNames(ego)的常量属性)
if(altEgo.always.has(property)| |!mask.hasOwnProperty(property))
Object.defineProperty(mask,property,Object.getOwnPropertyDescriptor(ego,property));
返回掩码;
}
altEgo.always=新集合(['name','length','prototype']);//要复制到掩码的属性
这成功地适用于OP末尾提到的所有三个场景

这里有一个测试平台,
ego
函数是
class foo
。正如您所看到的,被屏蔽的
foo
作为一个类使用时,其工作原理与原始的一样,甚至可以由
woo
类扩展。
foo
woo
的实例按预期运行,并且静态也可以工作。如果您调用
foo
与普通函数一样,
alt
也起作用

“严格使用”;
福班{
静态chk(){
log(`static${this.name}.chk()`);
}
静态getgetchk(){
log(`static${this.name}.getchk`);
}
建造师(a、b、c){
this.con=true;
log(`new${new.target.name}()`);
}
检查(){
log(`${this.constructor.name}inst.check();inst.con=`+this.con);
}
获取getcheck(){
log(`${this.constructor.name}inst.getcheck`);
}
}
console.dir(foo);
功能altEgo(alt,ego){
如果(typeof alt!==“function”)抛出新的TypeError(`alt必须是一个函数`);
如果(自我的类型!=“函数”)抛出新的类型错误(“自我必须是函数”);
常量掩码=函数(…参数){
return new.target?Reflect.construct(自我,args,new.target):alt(自我,面具,…args);
}
for(Object.getOwnPropertyNames(ego)的常量属性)
if(altEgo.always.has(property)| |!mask.hasOwnProperty(property))
Object.defineProperty(mask,property,Object.getOwnPropertyDescriptor(ego,property));
返回掩码;
}
altEgo.always=新集合(['name','length','prototype']);//要复制到掩码的属性
让alt=功能(自我、面具、目标){
log('alt function');
for(alt.clone的const属性)
Object.defineProperty(target、property、Object.getOwnPropertyDescriptor(ego.prototype、property));
回报目标;
}
中高音