函数柯里化

将一个接收多个参数的函数转换成一系列只接收单个参数的嵌套函数。

function sum(x, y, z) {
  return x + y + z;
}

function sum2(x) {
  return function (y) {
    return x + y;
  };
}

function curry(fn) {
  return function (x) {
    return function (y) {
      return function (z) {
        return fn(x, y, z);
      };
    };
  };
}
var curriedSum = curry((x, y, z) => {
  return x + y + z;
});
console.log("sum:" + sum(1, 2, 3));
console.log("sum2:" + sum2(1)(2));
console.log("curriedSum:" + curriedSum(1)(2)(3));

// curry(func) 的结果就是一个包装器 function(x)。
// 当它被像 curriedSum(1) 这样调用时,它的参数会被保存在词法环境中,然后返回一个新的包装器 function(y)。
// 然后这个包装器被以 2 为参数调用,最终它将该调用传递给原始的 func 函数。

偏函数

偏函数(Partial Function) 是指固定一个函数的部分参数,从而得到一个接收剩余参数的新函数

应用:

实现一个柯里化(currying)版本的 log 函数

// 1. 原始 log 函数
function log(date, importance, message) {
  alert(`[${date.getHours()}:${date.getMinutes()}] [${importance}] ${message}`);
}

// 2. 通用 curry 函数
function curry(fn){
  return function curried(...args){
    // 检查当前传入的参数数量是否足够调用原函数
    if (args.length >= fn.length) {
      return fn.apply(this, args)// 调用原函数
    }else{
      // 返回一个新函数以继续收集参数
      return function(...nextArgs){
        return curried.apply(this, args.concat(nextArgs))
      }
    }
  }
}

// 3. 柯里化 log
const curriedLog = curry(log);

// 4. 测试:正常调用
curriedLog(new Date(), "DEBUG", "normal call")
// 5. 测试:柯里化调用
curriedLog(new Date())("INFO")("curried call");
// 6. 偏函数
const now = new Date()
const logNow = log(new Date())
logNow("WARN", "partial applied")

// 7. 进一步偏函数
const debugNow = logNow('DEBUG')
debugNow('deep partial')