阅读 61

面试鄙视题 - 函数柯里化: 实现add(1)(2)(3)

简介

函数柯粒化, 在函数式编程中, 扮演着非常重要的角色. 比如要实现一个add(1)(2)(3), 确实难倒不少的面试者.

简单版实现.

最简单想到的是如下的实现.

const add = x => y=> z => x + y + z;
复制代码

但是如果我想支持这几种调用方式呢?

 // add(1, 2, 3);
 // add(1, 2)(3);
 // add(1)(2, 3);
复制代码

函数柯里化(curry)

概念很简单:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。

我们写一个柯里化函数.

const curry = (fn, ...args) => {
  // 函数的参数个数可以直接通过函数数的.length属性来访问
  if(fn.length === args.length){
    // 传入的参数大于等于原始函数fn的参数个数,则直接执行该函数
    return fn.call(fn, ...args);
  }

  // 传入的参数小于原始函数fn的参数个数时
  // 则继续对当前函数进行柯里化,返回一个接受所有参数(当前参数和剩余参数) 的函数
  return (...rest) => curry(fn, ...args, ...rest);
};
复制代码

使用curry来创建我们的add方法.

const add = (x,y,z) => x + y +z;
const curryAdd = curry(add);

console.log(curryAdd(1,2,3))
console.log(curryAdd(1,2)(3))
console.log(curryAdd(1)(2,3))
console.log(curryAdd(1)(2)(3))
复制代码

是不是看起来, 柯里化也不是那么的复杂.

柯里化有什么作用

  • 参数复用。当在多次调用同一个函数,并且传递的参数绝大多数是相同的,那么该函数可能是一个很好的柯里化候选。
  • 动态创建函数
  • 延迟计算。上面的例子已经比较好低说明了。