ES6类中的constr.apply(this,args)
我已经使用下面的函数来创build一些未知类的实例:
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'
我需要能够调用具有未知数量的参数的构造函数。 有关如何解决这个问题的任何想法?
有多种方法可以做到这一点:
-
使用
Function
对象的方法:Kernel.prototype._construct = function (constr, args) { return new (Function.prototype.bind.apply(constr, [null].concat(args))); };
这里我们将
args
作为bind
参数。 目标是有一个函数,可以调用没有arugments,所以我们可以调用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]...)
。 -
使用ES2015 Spread操作符 :
Kernel.prototype._construct = function (constr, args) { return new constr(...args); };
这简单得多,但是有两个问题:
- 它需要ES2015支持,甚至最新的Node(v4.2.1)也需要一个标志( –harmony_spreadcalls )。
- 这将产生一个语法错误,如果不支持,甚至不能有条件地执行,否则使用dynamic脚本(
eval()
/new Function(...)
) – 这是不build议的。
-
使用
Reflect
内置的对象。Kernel.prototype._construct = function (constr, args) { return Reflect.construct(constr, args); };
这也很简单,但在支持方面更为落后(基本上你必须使用babel)。
你可以通过将参数绑定到函数然后调用new来解决这个问题:
Kernel.prototype._construct = function (constr, args) { var F = constr.bind(null, args); return new F(); };
好的问题,但不是 ,根据ECMAScript§9.22,不能在ES6中调用没有new
关键字的构造函数 。
我在这里问了一个相同的问题: ES6:没有新关键字的调用类构造函数
我需要能够调用具有未知数量的参数的构造函数。 任何想法如何解决这个问题?
那么这不说(不)使用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中的类,则无法完成。
所以,就这样说,你究竟在做什么?