2

関数に渡され、一連の引数でそれを呼び出す関数を作成しようとしています。例えば:

function foo(func, args) {
  return func(args);
}

ただし、args に含まれる要素の数はわかりません。func は、任意の数の引数を取る任意の関数にすることができます。どうすればこれに対処できますか?

また、foo に渡された関数を保存し、以前に呼び出されていない場合にのみ呼び出したいとします。

次のようなことができますか:

var calledFuncs = [];
function foo(func, args) {
  if(calledFuncs.indexOf(func) === -1) {
    calledFuncs.push(func);
    return func(args);
  }
}

ありがとう、私は JavaScript での関数型プログラミングに少し慣れていません。

4

3 に答える 3

8

あなたが探しているfunc.apply

  • 最初の引数はコンテキスト別名this値です。これは変更したくないので、パススルーしてください。
  • 2 番目の引数は引数を含む配列であり、もちろん動的な長さにすることができます。

だからあなたはこれを行うことができます:

return func.apply(this, args);

あなたは2番目の問題(func(args)置き換えられたもの)にうまくアプローチしているようです。ただし、最初の呼び出しを除くすべての呼び出しに対してfoo返されるようになったため、呼び出された関数の戻り値を保存したい場合があります。undefined

于 2012-06-08T17:35:41.563 に答える
2

使用apply:

func.apply(this, args);

apply2 番目の引数として引数の配列を取ります。

の最初の引数は、呼び出している関数のスコープ内の のapply値になります。thisしたがって、現在thisまたは必要なものを渡すことができます。

2番目の質問に関する限り、それは名前付き関数に対してのみ機能します。func.name関数名を配列に格納するために使用できます。

var calledFuncs = [];
function foo(func, args) {
   if(calledFuncs.indexOf(func.name) === -1) {
      calledFuncs.push(func.name);
      return func(args);
   }
}

これは無名関数では機能せず、IE または Opera の名前付き関数では機能しません。おそらく次のように、それを解析する必要があります。

var name = func.toString().replace(/\n/g, "").replace(/\s*\(.*$/, "").replace(/^\s*function\s+/, "");

2 番目の質問に関する限り、現在行っていることを行うことができます。ただし、次の場合には機能しないと思います。

foo(function() {
}, []);

foo(function() {
}, []);

これらの関数の両方を呼び出します。

于 2012-06-08T17:35:33.067 に答える
1

あなたがしたいFunction.prototype.apply

func.apply(this,args);

コンテキスト (最初の引数) を、グローバルnullを取得するなど、必要なものに設定します (window現在のfunc(...)呼び出しで取得するように)。

質問とは直接関係ありませんFunction.prototype.callが、同様にコンテキストを設定できるが明示的なパラメーターを渡すことができる関連メソッドも参照してください。

于 2012-06-08T17:35:23.110 に答える