6

私の友人は、これらの両方のシナリオで機能する関数を書くように私に挑戦しました

add(2,4)  // 6
add(2)(4) // 6

私の本能は、自分自身を返す add() 関数を書くことでしたが、正しい方向に向かっているかどうかはわかりません。これは失敗しました。

function add(num1, num2){
    if (num1 && num2){
        return num1 + num2;
    } else {
        return this;
    }
}

alert(add(1)(2));

そこで、他の関数を返す関数や自分自身を返す関数について読み始めました。

私は努力を続けますが、誰かが巧妙な解決策を持っているなら、私はそれを見てみたいです!

4

8 に答える 8

11

毎回いくつの引数が渡されても、メソッドと関数コンテキスト ( )が にバインドされるカリー化された関数を作成しました。valueOf()thissum

/* add function */
let add = function add(...args) {
  const sum = args.reduce((acc, val) => acc + val, this);
  const chain = add.bind(sum);
  chain.valueOf = () => sum;
  return chain;
}.bind(0);

/* tests */
console.log('add(1, 2) = ' + add(1, 2));
console.log('add(1)(2) = ' + add(1)(2));
/* even cooler stuff */
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));
/* retains expected state */
let add7 = add(7);
console.log('let add7 = add(7)');
console.log('add7(3) = ' + add7(3));
console.log('add7(8) = ' + add7(8));

両方のメカニズムが必要な理由は、の本体が中間の部分適用add()の合計にアクセスするために呼び出された関数のバインドされたコンテキストを使用する必要があり、呼び出しサイトがアクセスするために (暗黙的または明示的に) メンバーを使用する必要があるためです。最終合計。valueOf()

于 2015-07-09T01:06:20.840 に答える
6

Dr.Dobs Journal には、この問題を正確に説明している「JavaScript のカリー化と部分関数」に関する記事があります。

この記事で見つけた 1 つの解決策は次のとおりです。

// a curried add
// accepts partial list of arguments
function add(x, y) {
     if (typeof y === "undefined") { // partial
        return function (y) {
              return x + y;
        };
     }
   // full application
   return x + y;
}
于 2015-07-09T09:55:03.163 に答える
0
var add = function(){
  // the function was called with 2 arguments
  if(arguments.length > 1)
    arguments.callee.first_argument = arguments[0];

  // if the first argument was initialized
  if(arguments.callee.first_argument){
    var result = arguments.callee.first_argument + arguments[arguments.length - 1];
    arguments.callee.first_argument = 0;

    return result;
  }else{// if the function was called with one argument only then we need to memorize it and return the same function handler 
    arguments.callee.first_argument = arguments.callee.first_argument || arguments[0];
    return arguments.callee;
  }
}
console.log(add(2)(4));
console.log(add(2, 4));

環境に依存する拡張ソリューション:

function add(){
  add.toString = function(){
    var answer = 0;
    for(i = 0; i < add.params.length; i++)
      answer += add.params[i];
    return answer;
  };

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

  return add;
}

console.log(add(2)(4)(6)(8))
console.log(add(2, 4, 6, 8));
于 2015-07-09T01:28:26.110 に答える
0
function add(num1, num2){
    if (num1 && num2) {
        return num1 + num2;
    } else if (num1) {
        return function(num2){return num1 + num2;};
    }
    return 0;
}
于 2015-07-09T00:53:41.910 に答える