ハックはハックですが、呼び出し構文は必要なものに似ており、元のクラスをまったく変更する必要がないため、おそらくこれは他のいくつかよりも少しエレガントです。
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"]);
したがって、これらが誰かに役立つことを願っています-元のコンストラクター関数をそのままにして、(現在選択されているソリューション/回避策に必要な2行とは異なり)1行のコードで目的の結果を取得できます。
フィードバックは大歓迎です。
更新:もう1つ注意すべき点は、これらの異なるメソッドを使用して同じタイプのインスタンスを作成してから、コンストラクターのプロパティが同じかどうかを確認することです。物体。私が意味することは、次のコードで最もよく示されています。
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() { /*...*/ };
上記で提供したソリューションは、役立つ場合と役に立たない場合があります。特定のニーズに最適なソリューションに到達するために何をしているのかを正確に理解する必要があります。また、私のソリューションを作成するために何が起こっているのかを認識する必要があります。」仕事。" 私のソリューションがどのように機能するか理解できない場合は、時間をかけて理解してください。
代替ソリューション:他のオプションを見落とすものではありません。これは、この猫の皮を剥ぐことができる他の方法の1つです(上記のアプローチと同様の注意事項があります)。これはもう少し難解です。
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;
};
楽しみ!