1const curry = (fn, ...args) => 
 2    // 函数的参数个数可以直接通过函数数的.length属性来访问
 3    args.length >= fn.length // 这个判断很关键!!!
 4    // 传入的参数大于等于原始函数fn的参数个数,则直接执行该函数
 5    ? fn(...args)
 6    /**
 7     * 传入的参数小于原始函数fn的参数个数时
 8     * 则继续对当前函数进行柯里化,返回一个接受所有参数(当前参数和剩余参数) 的函数
 9    */
10    : (..._args) => curry(fn, ...args, ..._args);
11
12function add1(x, y, z) {
13    return x + y + z;
14}
15const add = curry(add1);
16console.log(add(1, 2, 3));
17console.log(add(1)(2)(3));
18console.log(add(1, 2)(3));
19console.log(add(1)(2, 3));
20复制代码

柯里化有什么作用

主要有3个作用: 参数复用提前返回延迟执行

我们来简单的解释一下: 参数复用:拿上面 f这个函数举例,只要传入一个参数 z,执行,计算结果就是 1 + 2 + z 的结果,1 和 2 这两个参数就直接可以复用了。

提前返回 和 延迟执行 也很好理解,因为每次调用函数时,它只接受一部分参数,并返回一个函数(提前返回),直到(延迟执行)传递所有参数为止。

 1/**
 2 * @description: 将函数柯里化的工具函数
 3 * @param {Function} fn 待柯里化的函数
 4 * @param {array} args 已经接收的参数列表
 5 * @return {Function}
 6 */
 7const currying = function(fn, ...args) {
 8    // fn需要的参数个数
 9    const len = fn.length
10    // 返回一个函数接收剩余参数
11    return function (...params) {
12        // 拼接已经接收和新接收的参数列表
13        let _args = [...args, ...params]
14        // 如果已经接收的参数个数还不够,继续返回一个新函数接收剩余参数
15        if (_args.length < len) {
16            return currying.call(this, fn, ..._args)
17        }
18       // 参数全部接收完调用原函数
19        return fn.apply(this, _args)
20    }
21}
个人笔记记录 2021 ~ 2025