我已经使用以下函数在一段时间内创建了未知类的实例:
Kernel.prototype._construct = function (constr, args) {
function F() {
constr.apply(this, args); // EXCEPTION!
}
F.prototype = constr.prototype;
return new F();
};
如果我使用原型,一切正常:
function Person(name, surname) {
this.name = name;
this.surname = surname;
}
var person = Kernel._construct(Person, ["name", "surname"]); // WORKS!
但是,有些人在节点v4 +中使用我的库使用ES6本机类:
class Person {
constructor(name, surname) {
this.name = name;
this.surname = surname;
}
}
var person = Kernel._construct(Person, ["name", surname]); // EXCEPTION!
他们收到错误:
TypeError: Class constructors cannot be invoked without 'new'
我需要能够使用未知数量的参数调用构造函数。关于如何解决这个问题的任何想法?
答案 0 :(得分:9)
您可以通过多种方式实现这一目标:
使用Function
对象的方法:
Kernel.prototype._construct = function (constr, args) {
return new (Function.prototype.bind.apply(constr, [null].concat(args)));
};
我们在此applying args
作为bind
的参数。目标是拥有一个可以在没有调整的情况下调用的函数,以便我们可以调用new x()
。 bind
为我们这样做,但我们需要正确设置它。语法是:
func.bind(thisArg[, arg1][, args2...])
// calling the results from the above is like
// thisArg.func(arg1, arg2...);
我们希望使用constr
作为绑定函数,并使用args
中的项作为参数。我们不关心thisArg
。要做到这一点,我们需要"转换"参数的args
数组。 apply
调用会执行此操作:
func.apply(thisArg[, args]);
// calling the results from the above is like
// thisArg.func(args[0], args[1]...);
apply
实际上正在调用bind
。第一项[null]
非常重要,因为我们想要bind
thisArg
null
constr.bind(null, args[0], args[1]...)
,这样:Kernel.prototype._construct = function (constr, args) {
return new constr(...args);
};
。
使用ES2015 Spread operator:
eval()
这更简单,但有两个问题:
new Function(...)
/ Kernel.prototype._construct = function (constr, args) {
return Reflect.construct(constr, args);
};
) - 这是不建议的。 / LI>
使用对象中内置的Reflect
。
writetext
这也很简单,但在支持方面甚至更落后(基本上你必须使用babel)。
答案 1 :(得分:2)
你可以通过将参数绑定到函数然后在其上调用new来解决这个问题:
Kernel.prototype._construct = function (constr, args) {
var F = constr.bind(null, args);
return new F();
};
答案 2 :(得分:2)
很好的问题,但没有,根据ECMAScript §9.22,您无法在ES6中调用没有new
关键字的构造函数。
我在这里问了一个相同的问题: ES6: call class constructor without new keyword
我需要能够使用未知数量的参数调用构造函数。关于如何解决这个问题的任何想法?
这没有说明(不)使用new
关键字,但您可以在ES6构造函数中轻松使用可变参数
class Person {
constructor(name, surname, ...others) {
this.name = name;
this.surname = surname;
this.others = others || [];
}
}
let p = new Person('OweR', 'ReLoaDeD', 'a', 'b', 'c');
p;
//=> {"name":"OweR","surname":"ReLoaDeD","others":["a","b","c"]}
我怀疑这不是你所追求的。但是,如果您试图避免使用new
来调用ES6中的类,则无法完成。
所以,说到这一点,你究竟想要完成什么?