在javascript中创建对象时动态控制参数
我在javascript中有多个eatable类,例如:食物、饮料、零食。 每个类都需要一组不同的参数。我有另一个factory类,它创建发送给它的可食项的实例 我无法弄清楚如何使用此工厂动态选择可吃项并传递参数(以数组形式) 我提出了两个解决方案: 解决方案1:在javascript中创建对象时动态控制参数,javascript,oop,factory,Javascript,Oop,Factory,我在javascript中有多个eatable类,例如:食物、饮料、零食。 每个类都需要一组不同的参数。我有另一个factory类,它创建发送给它的可食项的实例 我无法弄清楚如何使用此工厂动态选择可吃项并传递参数(以数组形式) 我提出了两个解决方案: 解决方案1: var factory = function(eatable, argumentList){ var obj = new eatable(argumentList); return obj }; 这是一个问题,因为argum
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
请帮忙 您必须提供要应用的上下文,上下文就是您试图将参数应用到的对象。您当前传递的
{}
是Object类型的上下文
var factory = function(eatable, argumentList){
var obj = eatable.apply(new Eatable(), argumentList);
return obj
};
我不能使用没有多态性的工厂,因此如果您没有以扩展
Eatalbe
对象的方式创建这些eatable,您将无法执行此操作。您可以定义一个函数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;
您可以使用来正确设置原型链:
function factory(eatable, argumentList){
var obj = Object.create(eatable.prototyope);
return eatable.apply(obj, argumentList) || obj;
}
基本上就是这样的。啊,是的。我以前遇到过这个问题-你在JavaScript中。以前也曾提出过类似的问题: 问题很明显-
new
是一个关键字,而不是一个函数;和apply
只能用于函数。如果new
是一个函数而不是关键字
,那么我们可以将它与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, ...);
var object = Function.new.apply(constructor, [arg1, ...]);
您可以按如下方式调用构造函数:
var object = new constructor(arg1, ...);
var object = constructor.new(arg1, ...);
var object = Function.new.apply(constructor, [arg1, ...]);
你问这样做有什么好处?其实很简单。由于new
现在是一个函数而不是关键字,因此您可以将其与apply
结合使用,如下所示:
var object = new constructor(arg1, ...);
var object = constructor.new(arg1, ...);
var object = Function.new.apply(constructor, [arg1, ...]);
因此,您的可食工厂功能现在变为:
var factory = function(eatable, argumentList) {
var obj = Function.new.apply(eatable, argumentList);
return obj;
};
编辑:如果您的factory函数所做的只是采用一个eatable
构造函数和一个argumentList
并返回new.apply(eatable,argumentList)
,那么正如Bergi在他的评论中指出的那样,您可以将工厂定义如下:
var factory = Function.apply.bind(Function.new);
希望这有帮助。实现这一目标的另一种方法如下-
var _bind = Function.prototype.bind;
var factory = function(_constructor, _argumentList){
var obj = _bind.apply(_constructor, [null].concat(_argumentList));
return obj
};
如果必须同时传递对所需“类”的引用和参数列表,那么工厂函数的意义何在?我有一个很长的要初始化的类列表。我不想手动编写初始化它们的代码,而只是传递和数组,其中包含类的引用和必须提供给构造函数的参数。是的,但考虑到当前两种可能的解决方案基本上都是单行函数(不包括return语句)您也可以在处理数组的任何循环中只使用这一行。(虽然是的,但我知道你对这些解决方案不满意。)事实上,这就是我正在做的。列表中的每一项都调用工厂方法。我理解这一点。我是说,当工厂函数的(非常短的)主体可以直接进入您的循环时,工厂函数似乎是多余的。我想您不想更改构造函数,以便它们可以接受数组,您可以使用解决方案1?我想创建一个新的食品、饮料等对象,具体取决于在eatable变量中作为参数传递的内容。Eatable本身不是一个类,“应该是”?不,这只是一种方法——甚至你链接的文章也提到了其他不涉及分类的方法。在JS中,使用duck类型是相当常见的…为什么要强制使用多态性?类之间绝对没有关系。这不适用于eatable.apply(neweatable(),argumentList)代码>-假设eatable
可能引用的所有构造函数都将在没有参数的情况下“工作”。@nnnnnn你在问我这个吗?什么是eatable?在我的问题中,Eatable只是一个变量,而不是一个类。但是你可以将这个想法应用到你的Food()
,零食()
,等等。类:将每个类定义为一个空构造函数,并带有一个关联的init()
function…@Tushar Mathur:我刚才使用了Eatable
作为类定义,只是为了演示如何使用apply
调用单独的init
方法,并将参数作为参数传递。@nnnnnn我为什么要用空构造函数修改现有类?这不是一个解决方案,它是一个替代方案,将导致所有类中的更改。您为什么要这样做?因为这是实现工厂函数概念的一种方法,工厂函数可以传递参数。我只是想通过解释这个概念如何与类相关来回答您的第一个评论,而不是说这对您来说一定是最好的选择。var factory=Function.prototype.apply.bind(Function.prototype.new)代码>:-)顺便说一句,如果你已经发现了这个问题,不要忘记投票以重复的方式关闭…@Bergi你也可以做var factory=Function.apply.bind(Function.new)因为函数
本身是函数的一个实例。原型
。真是一个难题。哦,当然。一开始我以为你是在依赖:-/这是一个完美的解决方案!为了更基本的情况,我需要它,所以我做了var obj=Object.create(MyClass.prototype);返回MyClass.apply(obj,Array.prototype.slice.call(arguments))| | obj代码>@VictorFerreira:不知道我的代码有什么不同?请注意,切片
是无效的