我在javascript中有多个可食用的类,例如:食物,饮料,零食。 每个类都需要一组不同的参数。我有另一个工厂类,它创建一个发送给它的可食用项目的实例。
我无法弄清楚如何使用这个工厂动态选择可食用物品并传递参数(以数组形式)?
我想出了两个解决方案 - 解决方案1:
var factory = function(eatable, argumentList){
var obj = new eatable(argumentList);
return obj
};
这是一个问题,因为argumentList是一个数组。
解决方案2
var factory = function(eatable, argumentList){
var obj = eatable.apply({}, argumentList);
return obj
};
这并不能真正创建一个可食用类型的对象。
我真正想要的效果 假设我能够将argumentList转换为js参数类型对象,然后 -
var obj = new eatable(argumentList.toArguments());
obj instanceOf eatable; // should return true
请帮忙!
答案 0 :(得分:4)
啊,是的。我之前遇到过这个问题 - 你在JavaScript中can't use new
and apply
together。之前曾提出过类似的问题:Use of .apply() with 'new' operator. Is this possible?
问题非常明显 - new
是一个关键字,而不是一个函数;并且apply
只能用于某个函数。如果new
是函数而不是keyword
,那么我们可以将其与apply
结合使用。
要了解如何操作,让我们创建一个名为new
的函数,该函数完全符合关键字new
的作用:
Function.prototype.new = (function () {
function Factory(constructor, args) {
return constructor.apply(this, args);
}
return function() {
Factory.prototype = this.prototype;
return new Factory(this, arguments);
};
}());
现在不是按如下方式调用构造函数:
var object = new constructor(arg1, ...);
您可以按如下方式调用构造函数:
var object = constructor.new(arg1, ...);
这样做有什么好处?嗯,这很简单。由于new
现在是一个函数而不是关键字,因此您可以将其与apply
结合使用,如下所示:
var object = Function.new.apply(constructor, [arg1, ...]);
因此,您的可食用工厂功能现在变为:
var factory = function(eatable, argumentList) {
var obj = Function.new.apply(eatable, argumentList);
return obj;
};
编辑:如果您的所有工厂功能都是eatable
构造函数和argumentList
并返回new.apply(eatable, argumentList)
,那么Bergi在他的评论中指出可以如下定义factory
:
var factory = Function.apply.bind(Function.new);
希望这会有所帮助。
答案 1 :(得分:3)
您可以使用Object.create
正确设置原型链:
function factory(eatable, argumentList){
var obj = Object.create(eatable.prototyope);
return eatable.apply(obj, argumentList) || obj;
}
这基本上是new
operator的作用。
答案 2 :(得分:1)
您可以定义函数init
来初始化对象。
function Eatable(){
}
Eatable.prototype.init = function(/** arg1, arg2, arg3 **/){
// initialize object
}
在工厂功能
var eatable = new Eatable();
eatable.init.apply(eatable, /** pass arguments array here **/);
return eatable;
答案 3 :(得分:0)
您必须提供要应用的上下文,上下文是您尝试应用参数的对象。您当前传递的上下文{}
的类型为Object
var factory = function(eatable, argumentList){
var obj = eatable.apply(new Eatable(), argumentList);
return obj
};
我不能使用没有多态性的工厂,所以如果你没有以扩展Eatalbe
对象的方式创建那些 eatables ,你就无法做到。
答案 4 :(得分:0)
实现此目的的另一种方法如下 -
var _bind = Function.prototype.bind;
var factory = function(_constructor, _argumentList){
var obj = _bind.apply(_constructor, [null].concat(_argumentList));
return obj
};