几分钟搞懂函数柯里化!!

259 阅读4分钟

函数柯里化(Currying)是把一个多参数函数转换为一系列单参数函数的技术。简单来说,它允许将一个函数的多个参数逐个传入,而不是一次性传入所有参数。

🐟两个参数

举个栗子,正常的实现两个数字相加,应该如下所示

function sum(a,b){
    return a+b
}
console.log(sum(1,2)); //输出3

如果将其柯里化之后,可以变成这样的写法sum(1)(2),即多参数函数转换为单个参数函数,要实现这样的功能,我们如何改写呢?

首先把原函数只接受一个参数

function sum(a){
   return function sum(b){
      return a+b
   }
}

我们来放到vscode试一试可不可行

image.png

成功运行输出3

🐟三个参数

如果现在是 sum(1)(2)(3)呢? 我们还是老办法

function sum(a) {
    return function (b) {
        return function (c) {
            return a + b + c
        }
    }
}
console.log(sum(1)(2)(1));

很好理解,首先定义函数sum(a),这个函数接收一个参数a。 当调用sum(1)时,返回一个新的函数,这个新函数闭包了参数a的值为 1。

接着返回的这个新函数接收参数b。当调用sum(1)(2)时,再次返回一个新的函数,此时这个新函数闭包了参数a的值为 1 和参数b的值为 2。

最后这个新函数接收参数c。 当调用sum(1)(2)(1)时,在这个最内层的函数中,使用闭包中保存的ab的值,以及传入的c的值,计算并返回a + b + c的结果。 如果不知道闭包的概念的童鞋,可以去看看我讲解的闭包(前端之路-了解什么是闭包 ),再回头来看函数柯里化,保证你收获满满

image.png

这样一直写几个参数,几个参数的,代码也太不优雅了,我们就会想,如果能自己自定义参数的个数,是不是就很nice了。下面来和我一起去实现,我先给大家一段代码,然后细细和大家讲解一下

自定义参数

const curry = (fn, ...args) =>( args.length>fn.length? fn(...args) : (..._args) => curry(fn, ...args, ..._args)); 
function add1(x, y, z) {
     return x + y + z; 
}
const add = curry(add1);

首先第一行写的就是函数的柯里化,它用了三元表达式,如果传入的参数数量大于等于原始函数fn的参数个数,则直接执行该函数,即 fn(...args),当传入的参数数量小于原始函数 fn 的参数个数时,会执行 (..._args) => curry(fn,...args,..._args)

我们来解释一下 (..._args) => curry(fn,...args,..._args)。 这是一个箭头函数,不知道箭头函数的,我先给大家解释一下

在这个箭头函数中:

  • (..._args)表示函数的参数列表,这里使用了剩余参数语法,表示可以接受任意数量的参数,并将它们收集到一个名为_args的数组中。
  • =>是箭头函数的标志。
  • curry(fn,...args,..._args)是函数的表达式部分,这里调用了curry函数,并将原始函数fn、之前收集的参数args以及新传入的参数_args一起传递给它。

然后我们来解释一下表达式部分,这个返回的函数接受更多的参数 _args,当这个新函数被调用时,它会再次调用 curry 函数,把原始函数 fn、已有的参数 args 和新传入的参数 _args 一起传递进去。这样就继续进行柯里化的过程,不断收集参数,直到参数数量满足原始函数的要求。

在参数不足时返回一个新函数,该新函数在被调用时会再次调用柯里化函数curry,把原始函数及已收集和新传入的参数一并传递,继续柯里化过程以收集参数,直至满足原始函数的参数要求。

柯里化的实现不是很难,但他的实际开发作用场景还是不少的,下面我给大家总结了几点

  1. 函数复用:非常容易地为函数的一部分参数进行复用
  2. 延迟执行:使函数的执行被延迟到最后一个参数被传递进来的时候再进行
  3. 简单化函数:把多参数函数转换成单参数函数
  4. 函数组合:使不同的函数更加容易组合起来使用

🐟 END

前端面试还是会问到函数柯里化的,虽难不难,但是希望大家能理解透彻!一起互相学习,共勉!