如何调用具有动态参数数量的构造函数
How to call a constructor with dynamic amount of arguments?
我有一个构造函数,但我不知道它需要多少个参数,例如:
function someCtor(a,b,c){
var that = this;
that.a = a;
that.b = b;
that.c = c;
}
我需要创建一个函数,该函数将返回该构造函数的实例,并带有动态数量的参数:
function makeNew(ctor, arguments){
// this doesn't work, but it shows what I'm trying to achieve
return new ctor.apply(arguments);
}
我想使用函数传递动态参数给构造函数,如下所示:
var instanceOfCtor = makeNew(someCtor, [5,6,7]);
如何实现这个函数?
注意:请参阅ES2015兼容性说明。
首先创建一个对象,将其底层原型设置为构造函数上的prototype
属性通过Object.create
引用的对象,然后通过Function#apply
调用构造函数:
function makeNew(ctor, arguments){
var obj = Object.create(ctor.prototype);
var rv = ctor.apply(obj, arguments);
return rv && typeof rv === "object" ? rv : obj;
}
注意末尾的一点摆弄,所以我们正确地模拟了new
操作符:当你通过new
调用构造函数时,如果它返回一个非null
对象引用,那么它最终是new
表达式的结果;如果它返回其他任何东西(或什么都不返回),则结果是由new
创建的对象。所以我们效仿它。
即使在es5之前的浏览器上,你也可以模拟足够的Object.create
来做到这一点:
if (!Object.create) {
Object.create = function(proto, props) {
if (typeof props !== "undefined") {
throw new Error("The second argument of Object.create cannot be shimmed.");
}
function ctor() { }
ctor.prototype = proto;
return new ctor;
};
}
ES2015兼容性说明
如果你调用的构造函数是通过ES2015的class
语法创建的,那么上面的方法将不起作用,因为你不能以这种方式调用ES2015的class
构造函数。例如:
class Example {
constructor(a, b) {
this.a = a;
this.b = b;
}
}
const e = Object.create(Example.prototype);
Example.apply(e, [1, 2]); // TypeError: Class constructor Example cannot be invoked without 'new' (or similar)
好消息是,这只会发生在ES2015+兼容的JavaScript引擎上,并且只有当构造函数是通过class
创建的;坏消息是这是可能发生的。
那么如何让你的makeNew
防弹呢?
事实证明这很容易,因为ES2015还添加了Reflect.construct
,它确实做了你想要makeNew
做的事情,但它的方式与class
构造函数和function
构造函数兼容。所以你可以功能检测Reflect.construct
并使用它,如果它存在(ES2015 JavaScript引擎,所以一个构造函数可能已经用class
创建),如果它不存在(ES2015之前的引擎,不会有任何class
构造函数):
var makeNew; // `var` because we have to avoid any ES2015+ syntax
if (typeof Reflect === "object" && Reflect && typeof Reflect.construct === "function") {
// This is an ES2015-compatible JavaScript engine, use `Reflect.construct`
makeNew = Reflect.construct;
} else {
makeNew = function makeNew(ctor, arguments){
var obj = Object.create(ctor.prototype);
var rv = ctor.apply(obj, arguments);
return rv && typeof rv === "object" ? rv : obj;
};
}
这是纯ES5语法,所以运行在ES5引擎上,但使用ES2015的Reflect.construct
如果它存在。
- Facebook共享动态参数链接
- 在动态创建的元素中包含参数的事件处理程序
- Javascript 动态将参数化函数分配给 onclick
- Emberjs - 将参数动态绑定到视图
- 在 angularjs 的 ga 命令中设置动态参数
- 限制与AngularJS状态匹配的动态URL参数的最佳方式
- Jquery-将参数动态传递给函数
- 通过参数将传递的函数分配给动态创建的输入类型的onclick事件
- 如何为jQuery帖子输入动态数据参数
- Javascript动态锚点参数
- Jquery 在 Firefox 中的自定义对象参数(动态导航加载动态内容)
- 使用来自 json 对象的参数动态调用方法/函数
- 根据参数动态调整对象名称
- 根据泛型函数中的参数动态添加ajax处理程序
- 使用传递给函数的参数动态地从一组数组中检索值
- 使用参数动态引用json对象
- 由于某些原因,基于路由参数动态注入特定工厂会失败
- 用不同的参数动态初始化服务
- 如何根据参数动态构建JavaScript指令
- 基于函数参数动态调用javascript函数