函数柯里化

什么是函数柯里化

把接收多个参数的原函数转换成一个可接收单一参数的新函数,新函数调用后会再返回一个函数,该函数可以继续接收剩余的参数,直到传入的参数和原函数的参数数量一致时,才会调用原函数。 具体可以参考 lodash 库中的 _.curry() 方法。

为什么要柯里化/柯里化的意义是什么

  1. 延迟调用,将多参函数进行拆分,参数数量和原函数一致时才真正的调用。
  2. 函数中某个参数大部分时候是固定的,柯里化后可以省去固定参数的重复书写。
  3. 类似于 bind() 这种方法的应用,对原函数进行一些更改,再返回更改后的函数。

如何实现柯里化

柯里化函数会接受到固定参数,然后再柯里化函数里面,返回一个新的函数,接收剩余参数。 简易的实现一个 bind()方法。

Function.prototype.mybind = function (thisArg) {
  if (typeof this !== 'function') {
    return
  }
  var _self = this
  var args = Array.prototype.slice.call(arguments, 1)
  return function () {
    return _self.apply(
      thisArg,
      args.concat(Array.prototype.slice.call(arguments))
    )
  }
}

简单模拟 _.curry()实现原理

个人理解就是递归调用,直到传入的参数数量和原函数的参数数量一致时,才去调用原函数。

/**
 * 柯里化函数 将多个参数的函数进行柯里化
 * @param {*} fn 接收一个有多个参数的纯函数
 * @returns 返回柯里化后的函数 调用时如果实参长度小于原函数形参长度将继续返回接收剩余参数的函数
 * 直到参数长度相等才会执行原函数
 */

const curry = function (fn) {
  return function curried(...args) {
    if (args.length < fn.length) {
      return (...a) => curried(...args.concat(Array.from(a)))
    }
    return fn(...args)
  }
}

const sum = (a, b, c) => a + b + c
const curried = curry(sum)

// test
// console.log(curried(1, 2, 3))
// console.log(curried(1)(2, 3))
// console.log(curried(1)(2)(3))