接下来马上开始WWH(what,why,how)

W——什么是柯里化

在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。

——百度百科《柯里化》

下面说一点人话

cfn(1)(2)(3)来实现fn(1,2,3)的效果

W——为什么要柯里化

把一个抽象函数(即只知道参数列表和返回类型的函数模版)作为参数送给另一个函数。这样实现了调用和实现的分离

解决了某些方法只接受一个参数的问题

H——怎么实现柯里化

重头戏开始

image-20200920160207086

先来看一个简单的二元函数转一元函数的示例

// 接收一个函数,返回一个柯里化的函数
function curry(fn) {
  return function (x) {
    return function (y) {
      return fn(x, y)
    }
  }
}
function add(x, y) {
  return x + y
}

const cAdd = curry(add)

console.log('add方法-' + add(1, 2));
console.log('cAdd方法-' + cAdd(1)(2));

image-20200920161321007

类似于在z=x+y中,先确定了x的值,然后下一步把y带入,计算出结果

再来看一个实际一点的用法

const arr = [
  {
    name: 'zhangsan',
    age: 12
  },
  {
    name: 'lisi',
    age: 12
  },
  {
    name: 'wangwu',
    age: 12
  },
]
const getObj = (name, item) => {
  return item.name === name
}
const cfn = curry(getObj)
// console.log(cfn('lisi').toString());
let result = arr.filter(cfn('lisi'))
console.log(result);

这段代码中首先定义了一个对象数组,然后使用数组的filter方法来获取某个对象,getObj方法接收两个参数,返回一个boolean值,柯里化之后只需要接收一个参数,因为是在filter函数的回调函数中,所以会自动将数组中的每一项作为参数执行回调函数

image-20200920161722255

这里可能会很难绕出来,打印一下cfn('lisi')看一下

image-20200920161941983

可以看到cfn('lisi')就只是一个函数,参数y就是filter遍历时的item

image-20200920162121815

这只是二元柯里化,那我要是好多参数怎么办,再写一个?几个参数套几层闭包?

image-20200920162440895

当然有一劳永逸的方法

function curry(fn) {
  const length = fn.length;
  const curryFn = (args) => (arg) => {
    const curryArgs = args.concat(arg);
    if (curryArgs.length === length) {
      return fn(...curryArgs);
    }
    return curryFn(curryArgs);
  }
  return curryFn([]);
}

试一下

image-20200920163236366

GOOD!!!


前端小白