柯里化是一个超纲内容,也很难,读者可以不用看,柯里化实际上就是柯里化函数,属于函数式编程的范畴,柯里化函数的作用就是:固定一个函数的某些参数,得到该函数的剩余参数的一个新函数,如果没有剩余参数,则调用。
这个概念非常抽象,这里从使用者的角度出发看一下,假设有一个别人写好的函数 A,这个函数接受两个参数 a 和 b,但是在我这个场景下,参数 a 是固定不变的,此时就可以使用柯里函数将这个函数 A 改造一下,把它第一个参数固定下来,让他只能接受一个参数,简单而言,柯里化函数就是用来将原函数的一些参数固定,返回一个新的函数,这个新的函数如果参数足够,就会直接调用,如果参数不够,就会再次柯里化固定一些参数。
js
/**
* curry函数用于将多参数函数转换为单参数函数,以便逐步传递参数。
* @param {Function} fn 需要被转换的多参数函数。
* @returns {Function} 返回一个逐步接受参数并最终执行原函数的单参数函数。
*/
function curry(fn) {
var args = [].slice.call(arguments, 1); // 将除了第一个参数外的所有参数转换为数组。
var that = this; // 保存当前执行上下文。
return function () {
var currentArg = Array.from(arguments); // 将当前调用传递的参数转换为数组。
var totalArg = args.concat(currentArg); // 将之前保存的参数和当前参数合并。
if (totalArg.length < fn.length) { // 如果累计参数数量小于原函数参数数量,继续递归。
totalArg.unshift(fn) // 将原函数添加到参数数组的开头。
return that.curry.apply(null, totalArg); // 在当前上下文中递归调用curry函数。
} else { // 如果参数数量足够,执行原函数。
return fn.apply(null, totalArg); // 使用apply调用原函数,确保所有参数被正确传递。
}
}
}
/**
* 用于测试的函数,接受三个参数并求和。
* @param {number} a 第一个参数。
* @param {number} b 第二个参数。
* @param {number} c 第三个参数。
* @returns {number} 参数之和。
*/
function test(a, b, c) {
console.log(a + b + c);
}
// 直接调用test函数,传入全部参数。
test(2, 3, 4);
// 将test函数通过curry转换,预先传入第一个参数1。
var test1 = curry(test, 1);
// 使用test1,传入第二个参数2。
test1(2, 3);
// 上述调用相当于test(1, 2, 3),现在将test1的返回结果(即curried的test函数)赋值给test2。
var test2 = test1(5);
// 调用test2,传入最后一个参数6。全部参数已传入,将执行原test函数。
test2(6);- 函数
curry接受一个参数fn,代表要进行柯里化的函数。 - 在函数内部,首先通过
arguments对象和slice方法获取除第一个参数外的所有参数,并将其保存在args数组中。 - 然后,使用
this保存当前上下文,并返回一个新的函数。 - 这个新的函数接受任意数量的参数,并将其保存在
currentArg数组中。 - 接着,将
args和currentArg数组进行合并,得到一个新的数组totalArg。 - 如果
totalArg的长度小于fn的参数长度,则将fn放入totalArg数组的开头,并通过curry方法递归调用自身,并使用apply方法将null作为上下文传入,将totalArg作为参数传入。 - 如果
totalArg的长度大于等于fn的参数长度,则通过apply方法将null作为上下文传入,将totalArg作为参数传入,并执行fn函数。
实际上,柯里化的作用就是固定参数,在函数式编程中,柯里化函数的作用就是把一些通用函数的参数变少,可以更加方便我们使用。