3

私はEloquentJavascriptを読んでいて、以下の例を理解するのに苦労しています。誰でも行ごとの説明ができるでしょうか?具体的には、最初のループが1から始まる理由と、pushメソッドがknownArgsと引数の両方で使用されている理由について混乱しています。これは「部分適用」に関連していることは知っていますが、正確に何が起こっているのかを行ごとに詳しく説明したいと思います。

var op = {
 "+": function(a,b){return a + b;}
};

function partial(func) {
 var knownArgs = arguments;

 return function() {
  var realArgs = [];

  for (var i=1; i<knownArgs.length; i++)
   realArgs.push(knownArgs[i]);

  for (var i=0; i<arguments.length; i++)
   realArgs.push(arguments[i]);

  return func.apply(null, realArgs);
 };
}

map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]);
4

2 に答える 2

2

knownArgs変数は、呼び出されargumentsたときの値のコピーを保持します。partial()その呼び出しは別の関数を返し、そのコード内にargumentsはまったく異なるリストがあります—それらはその返された関数に渡される引数です。言い換えると:

var p = partial(someFunction、 "hello"、 "world");

p()呼び出されると、knownArgs「hello」と「world」になりsomeFunctionます(もちろん、最初のループは1から始まることに注意してください)。の呼び出しがp()次のようになっている場合:

p( "how"、 "are"、 "you");

次に、最初に「hello」と「world」をrealArgs(から)リストにプッシュし、次に、から、にknownArgs渡される3つのパラメーターをプッシュします。p()arguments

編集—評価方法の段階的な内訳map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]);

  1. まず、op["+"]評価する必要があります。私はそれが関数を返すと推測しています、おそらく次のようなものです:

    function add(a, b) {
      return a + b;
    }
    
  2. その「追加」関数と値1がに渡されpartial()ます。partial()したがって、arguments疑似配列の内部は次のようになります。

    [ add, 1 ]
    

    つまり、最初のパラメーターはfromの「add」関数でop["+"]あり、2番目のパラメーターはその値1です。partial()匿名関数を返す前に実際に行う唯一のことは、に保存argumentsすることknownArgsです。奇妙なarguments疑似変数には、関数呼び出しごとに常に新しい値が割り当てられるため、これを行う必要があります。匿名関数のコードが後でアクセスできるように、ここに保存されています。

  3. ここで、から返された無名関数partial()とその偶数の配列を使用して、を呼び出しますmap()。その関数はおそらく次のようになります(私は本を持っていません):

    function map(fn, list) {
      var i, result = [];
      for (i = 0; i < list.length; ++i) {
        result.push( fn( list[i] ) );
      }
      return result;
    }
    

    の内部map()では、最初のパラメーターは、の前の呼び出しから返された無名関数partial()です。その関数は何をしますか?partial()それは、最初の呼び出しを除いて、元の呼び出しからのパラメーターと、それに渡されたパラメーターを組み合わせたものです。関数は1つのmap()パラメーターのみを渡すため、無名関数への各呼び出しで結果として得られるパラメーターリストは、1渡される値にpartial()なり、各反復で、リストとは異なる偶数になります。

より簡単な例は、電話をかけたときに何が起こるかを検討することです。

partial(op["+"], 1)(2);

つまり、呼び出しpartial()てすぐにその戻り値(無名関数)を使用する場合です。効果は、呼び出しと同じになります。

add(1, 2);
于 2012-11-11T21:44:08.147 に答える
1

最初のループはknownArgs[0]、引数ではなく関数が含まれているため、ゼロではなく1から始まります。

push単一の要素を配列に追加します。これは、アレイを構築するためのかなり一般的な方法です。

  var realArgs = [];

  for (var i=1; i<knownArgs.length; i++)
    realArgs.push(knownArgs[i]);

  for (var i=0; i<arguments.length; i++)
    realArgs.push(arguments[i]);

knownArgsおよびから連結された新しい配列を作成しますargumentsknownArgsカレーされた引数と関数(に追加されていないrealArgs)を保持し、arguments呼び出されたときに関数に提供される引数です。

于 2012-11-11T21:43:58.367 に答える