JavaScript で、オブジェクト インスタンス (演算子経由new
) を作成し、コンストラクターに任意の数の引数を渡したいのですが。これは可能ですか?
私がやりたいことは次のようなものです (ただし、以下のコードは機能しません)。
function Something(){
// init stuff
}
function createSomething(){
return new Something.apply(null, arguments);
}
var s = createSomething(a,b,c); // 's' is an instance of Something
答え
ここでの回答から、オペレーター.apply()
に電話をかける組み込みの方法は存在しないことが明らかになりましたnew
。ただし、この問題に対して非常に興味深い解決策がいくつか提案されました。
私が好んだ解決策はこれはマシュー・クラムリーからのものだ(プロパティを渡すように変更しましたarguments
):
var createSomething = (function() {
function F(args) {
return Something.apply(this, args);
}
F.prototype = Something.prototype;
return function() {
return new F(arguments);
}
})();
ベストアンサー1
ECMAScript5のFunction.prototype.bind
物事はかなりきれいになります:
function newCall(Cls) {
return new (Function.prototype.bind.apply(Cls, arguments));
// or even
// return new (Cls.bind.apply(Cls, arguments));
// if you know that Cls.bind has not been overwritten
}
以下のように使用できます。
var s = newCall(Something, a, b, c);
あるいは直接的にも:
var s = new (Function.prototype.bind.call(Something, null, a, b, c));
var s = new (Function.prototype.bind.apply(Something, [null, a, b, c]));
これと評価ベースのソリューション次のような特殊なコンストラクタを使用しても常に機能するのは、次のものだけですDate
。
var date = newCall(Date, 2012, 1);
console.log(date instanceof Date); // true
編集
少し説明します。new
限られた数の引数を取る関数を実行する必要があります。bind
メソッドを使用すると、次のように実行できます。
var f = Cls.bind(anything, arg1, arg2, ...);
result = new f();
キーワードはのコンテキストをリセットするので、パラメータanything
はあまり重要ではありません。ただし、構文上の理由から必要です。呼び出しについては、次のようにします。可変数の引数を渡す必要があるため、次のようにします。new
f
bind
var f = Cls.bind.apply(Cls, [anything, arg1, arg2, ...]);
result = new f();
これを関数でラップしてみましょう。Cls
は引数 0 として渡されるので、 になりますanything
。
function newCall(Cls /*, arg1, arg2, ... */) {
var f = Cls.bind.apply(Cls, arguments);
return new f();
}
実際には、一時f
変数はまったく必要ありません。
function newCall(Cls /*, arg1, arg2, ... */) {
return new (Cls.bind.apply(Cls, arguments))();
}
bind
最後に、それが本当に必要なものであることを確認する必要があります。 (Cls.bind
は上書きされている可能性があります)。これを に置き換えるFunction.prototype.bind
と、上記のような最終結果が得られます。