Hacks are hacks are hacks,但也许这个比其他一些更优雅,因为调用语法与你想要的相似,你根本不需要修改原始类:
Function.prototype.build = function(parameterArray) {
var functionNameResults = (/function (.{1,})\(/).exec(this.toString());
var constructorName = (functionNameResults && functionNameResults.length > 1) ? functionNameResults[1] : "";
var builtObject = null;
if(constructorName != "") {
var parameterNameValues = {}, parameterNames = [];
for(var i = 0; i < parameterArray.length; i++) {
var parameterName = ("p_" + i);
parameterNameValues[parameterName] = parameterArray[i];
parameterNames.push(("parameterNameValues." + parameterName));
}
builtObject = (new Function("parameterNameValues", "return new " + constructorName + "(" + parameterNames.join(",") + ");"))(parameterNameValues);
}
return builtObject;
};
现在您可以执行以下任一操作来构建对象:
var instance1 = MyClass.build(["arg1","arg2"]);
var instance2 = new MyClass("arg1","arg2");
当然,有些人可能不喜欢修改 Function 对象的原型,因此您可以这样做并将其用作函数:
function build(constructorFunction, parameterArray) {
var functionNameResults = (/function (.{1,})\(/).exec(constructorFunction.toString());
var constructorName = (functionNameResults && functionNameResults.length > 1) ? functionNameResults[1] : "";
var builtObject = null;
if(constructorName != "") {
var parameterNameValues = {}, parameterNames = [];
for(var i = 0; i < parameterArray.length; i++) {
var parameterName = ("p_" + i);
parameterNameValues[parameterName] = parameterArray[i];
parameterNames.push(("parameterNameValues." + parameterName));
}
builtObject = (new Function("parameterNameValues", "return new " + constructorName + "(" + parameterNames.join(",") + ");"))(parameterNameValues);
}
return builtObject;
};
然后你会这样称呼它:
var instance1 = build(MyClass, ["arg1","arg2"]);
所以,我希望这些对某人有用 - 它们允许您不理会原始构造函数,并在一行简单的代码中获得您所追求的(与当前选择的解决方案/解决方法所需的两行不同。
欢迎和赞赏反馈。
更新:要注意的另一件事 - 尝试使用这些不同的方法创建相同类型的实例,然后检查它们的构造函数属性是否相同 - 如果您需要检查类型目的。下面的代码最好地说明了我的意思:
function Person(firstName, lastName) {
this.FirstName = firstName;
this.LastName = lastName;
}
var p1 = new Person("John", "Doe");
var p2 = Person.build(["Sara", "Lee"]);
var areSameType = (p1.constructor == p2.constructor);
尝试使用其他一些技巧,看看会发生什么。理想情况下,您希望它们是同一类型。
警告:如评论中所述,这不适用于那些使用匿名函数语法创建的构造函数,即
MyNamespace.SomeClass = function() { /*...*/ };
除非你像这样创建它们:
MyNamespace.SomeClass = function SomeClass() { /*...*/ };
我上面提供的解决方案可能对您有用,也可能对您没有用,您需要准确了解您正在做什么才能为您的特定需求找到最佳解决方案,并且您需要了解我的解决方案正在发生的事情“工作。” 如果您不了解我的解决方案是如何工作的,请花时间弄清楚。
替代解决方案:没有一个可以忽略其他选项,这是您可以给这只猫剥皮的其他方法之一(与上述方法类似的警告),这个更深奥一点:
function partial(func/*, 0..n args */) {
var args = Array.prototype.slice.call(arguments, 1);
return function() {
var allArguments = args.concat(Array.prototype.slice.call(arguments));
return func.apply(this, allArguments);
};
}
Function.prototype.build = function(args) {
var constructor = this;
for(var i = 0; i < args.length; i++) {
constructor = partial(constructor, args[i]);
}
constructor.prototype = this.prototype;
var builtObject = new constructor();
builtObject.constructor = this;
return builtObject;
};
享受!