JavaScript curry / schönfinkeln

JavaScript curry / schönfinkeln

本文关键字:#246 nfinkeln sch curry JavaScript      更新时间:2023-09-26

假设我声明了以下函数

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};

我想做的是显而易见的,我想curry add函数,它本身工作得很好

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

不知怎么的,它返回NaN,我不知道我做错了什么…有人知道吗?

这里有一个差一的错误:return fn.apply(argstotal)

Function.prototype.apply的第一个参数是一个作用域,this在调用中的值,不是第一个参数。如果要从您的curry函数中打印出arguments,您将看到:

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);

你可以很容易地用两种方法修复这个问题:

  1. this传递给柯里化函数
  2. 忽略this,不为柯里函数设置

第一个选项可能更好,因为它不会让开发人员感到惊讶。你可以使用:

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);

第二个选项可以通过fn.apply(null, argstotal)实现