JavaScript咖喱/schönfinkeln

时间:2016-11-15 19:45:16

标签: javascript

假设我声明了以下函数

function curry(fn) {
    var args = [];
    // push everything but function itself into args
    for (var i = 1; i < arguments.length; ++i) {
        args.push(arguments[i]);
    }
    return function() {
        var args2 = [];
        for (var i = 0; i < arguments.length; i++) {
            args2.push(arguments[i]);
        }
        var argstotal = args.concat(args2);
        return fn.apply(argstotal);
    };
}

function add(a,b){return a + b};

我想要做的事情显而易见,我想要讨论自己运作良好的添加功能

var addCurry = curry(add);
addCurry(10, 20, 12314) // should deliver 30, gives NaN

不知怎的,它回归NaN,我不知道我做错了什么......有人有个主意吗?

1 个答案:

答案 0 :(得分:3)

您在此处有一个错误:return fn.apply(argstotal)

Function.prototype.apply的第一个参数是范围,调用中this的值,不是第一个参数。如果您要从curried函数中打印出arguments,您会看到:

&#13;
&#13;
function curry(fn) {
  var args = [];
  // push everything but function itself into args
  for (var i = 1; i < arguments.length; ++i) {
    args.push(arguments[i]);
  }
  return function() {
    var args2 = [];
    for (var i = 0; i < arguments.length; i++) {
      args2.push(arguments[i]);
    }
    var argstotal = args.concat(args2);
    return fn.apply(argstotal);
  };
}

function add(a, b) {
  console.log('debug', this, arguments);
  return a + b;
}

var cadd = curry(add, 1);
cadd(2);
&#13;
&#13;
&#13;

您可以通过两种方式轻松解决此问题:

  1. this传递给咖喱功能
  2. 忽略this,不要将其设置为咖喱功能
  3. 第一种选择可能更好,因为它会让开发人员感到惊讶。您可以使用以下方法实现:

    &#13;
    &#13;
    function curry(fn) {
      var args = [];
      // push everything but function itself into args
      for (var i = 1; i < arguments.length; ++i) {
        args.push(arguments[i]);
      }
      return function() {
        var args2 = [];
        for (var i = 0; i < arguments.length; i++) {
          args2.push(arguments[i]);
        }
        var argstotal = args.concat(args2);
        return fn.apply(this, argstotal); // <-- only change
      };
    }
    
    function add(a, b) {
      console.log('debug', /* this, */ arguments);
      return a + b;
    }
    
    var cadd = curry(add, 1);
    cadd(2);
    &#13;
    &#13;
    &#13;

    可以使用fn.apply(null, argstotal)实现第二个选项。