函数柯里化

223 阅读1分钟

两种函数柯里化

1. 知道函数的参数个数

/**
 * @params { Function } fn 需要柯里化的函数
 * @return { Function | Number }
 */
function curry(fn) {

  // 利用闭包维护一个 args 数组来保存依次传进的参数
  // 利用 fn.length 来控制函数的边界
  let [args, l] = [[], fn.length]
  
  // 如果传入的参数不够就返回一个接受下一个参数的函数 _
  // 当传入足够的参数以后,返回函数执行结果
  // note:记住在函数执行完时清空闭包内的 args,不然会影响下次调用。
  return function _(prop) {
    return args.push(prop) < l ? _ : fn(...args.splice(0,args.length));
  }
}

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

let curryAdd = curry(add)
curryAdd(1)(2)(3)    // 6
curryAdd(5)(5)(5)    //15

2. 函数参数未知

/**
 * @params { Function } fn 需要柯里化的函数
 * @return { Function | Number }
 */
function curry(fn) {

  // 与前者类似,不过函数边界是由 prop 来控制
  // 当传入的 prop 为空时,返回函数执行结果。
  // note:注意清除 args。
  let args = []
  return function _(...prop) {
    if(prop.length){
      args.push(...prop);
      return _;
    } else {
      return fn(...args.splice(0, args.length))
    } 
  }
}

function add(...args){
  return args.reduce((sum, item)=>{
    return sum + item;
  }, 0)
}

let curryAdd = curry(add)
curryAdd(1)(2)(3)(5)(45)()
curryAdd(1, 2, 3)(16)()

附:

手写数组扁平化

function flat(arr){
  return arr
    .reduce( (list, item) 
      => Array.isArray(item) 
        ? [...list,...flat(item)] 
          : [...list, item] , [])
}

flat([1,2,3,[4,5,[6, [7]]]])  // [ 1, 2, 3, 4, 5, 6, 7 ]

更多函数式编程内容点此查看。