基本用法
当我们使用柯里化函数时,我们将一个接收多个参数的函数转换为一系列接收一个参数的嵌套函数。这些嵌套函数会在每次调用时返回一个新的函数,直到所有参数都被收集完毕为止。最后一个函数将返回原始函数的结果。这样做的好处是,我们可以在不同时刻提供各个参数,这种灵活性使得我们可以更好地控制函数的应用。
下面是一个简单的例子,说明如何使用柯里化函数来定义一个加法器函数:
function add(x) {
return function(y) {
return x + y;
};
}
const add5 = add(5); // 此时返回一个接收一个参数的函数
console.log(add5(3)); // 输出 8
console.log(add5(7)); // 输出 12
在这个例子中,我们使用了柯里化函数来将一个接收两个参数的函数转换为一系列嵌套函数,每个函数只接收一个参数。我们首先调用 add(5) 函数,它返回一个接收一个参数的函数,该函数将 5 与传入的参数相加并返回结果。我们将这个函数存储在变量 add5 中,然后可以使用它来执行加法操作。
通过这种方式,我们可以方便地创建可重用的函数,这些函数可以在不同的上下文中使用,而无需重复编写相同的代码。
常用场景
function curry(func) {
return function curried(...args) {
if (args.length >= func.length) {
return func.apply(this, args);
} else {
return function (...args2) {
return curried.apply(this, [...args, ...args2]);
};
}
};
}
function sum(a, b, c) {
return a + b + c;
}
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
上述代码实现了一个通用的柯里化函数 curry,这个函数接收一个函数作为参数,并返回一个新的函数。新的函数接收一个参数列表,并在适当的时候,将这些参数传递给原始函数进行计算。
在 curry 函数内部,它首先返回了一个新函数 curried,这个函数的参数使用了 rest parameter(即 ...args),这样可以接受任意数量的参数。
接下来,函数会检查传递给 curried 的参数数量是否足够调用原始函数了。如果足够,那么就使用 apply 方法调用原始函数,并将参数列表传递给它。
否则,curried 函数返回另一个函数,这个函数也接受参数列表,然后将这些参数列表与之前收集到的参数列表合并,并再次调用 curried 函数。这样,我们可以在多次调用函数时逐步积累参数,直到满足原始函数的参数数量为止。
最后,我们使用 curry 函数定义了一个新的函数 curriedSum,该函数是通过将 sum 函数传递给 curry 函数创建的。我们可以使用 curriedSum 函数来计算任意数量的数字之和,由于上面的柯里化函数的实现,我们可以将多个函数调用链式地链接起来,如 curriedSum(1)(2)(3),最终输出结果为 6。
在 curry 函数的实现中,...args 是用来接收每次调用柯里化函数传入的参数的,而不是用来接收整个参数列表的。
在 curriedSum(1)(2)(3) 这行代码中,第一次调用传入了参数 1,这时候 curried 函数内部的 ...args 就是 [1]。第二次调用传入参数 2,此时 curried 函数内部的 ...args 就是 [1, 2]。第三次调用传入参数 3,此时 curried 函数内部的 ...args 就是 [1, 2, 3]。
因此,在最后一次调用时,curried 函数内部的 ...args 确实包含了所有传入的参数 [1, 2, 3],但这并不意味着整个参数列表都被传递给了 curry 函数。相反,每次调用都只传递一个参数,并将它们逐渐累积,直到满足原始函数的参数数量为止。
可以理解为: 这个函数前几次都在累积函数参数,累积到最后调用函数的次数跟传入参数的长度一致时才调用计算的函数
在 curriedSum(1)(2)(3) 的例子中,第一次调用 curriedSum(1),返回一个新的函数 curried,此时内部的 ...args 变量是 [1]。第二次调用 curried(2),返回另一个新的函数 curried,此时内部的 ...args 变量是 [1, 2]。第三次调用 curried(3),此时内部的 ...args 变量是 [1, 2, 3],这时候参数数量已经达到了原始函数 sum 的参数数量,所以会立即计算并返回结果 6。