函数柯里化(Currying)是一种将使用多个参数的函数转换成一系列使用一个参数的函数的技术。举例来说明,一个普通的函数可能接受两个参数然后执行操作:
function add(a, b) {
return a + b;
}
这个函数接受两个参数a和b
,然后返回它们的和。
柯里化版本的add
函数可以是这样的:
function curryAdd(a) {
return function(b) {
return a + b;
};
}
这个curryAdd就是一个柯里化函数,它可以接受第一个参数a并返回一个新的函数,这个新函数接受第二个参数b并返回他们的和,这样就可以实现逐个传递参数:
const addTen = curryAdd(10); // 这里已经给a传值了
console.log(addTen(5)); // 15,现在给b传值
实现函数柯里化的通用方式是使用闭包。闭包是一个有权访问另一个函数作用域内变量的函数。当一个函数返回另一个函数,并且这个返回的函数引用了外部函数的变量,那么这些变量会一直存在,即使外部函数已经执行完毕。
我们可以写一个通用柯里化函数,这个函数可以将传进来的任意函数转化为柯里化函数:
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.concat(args2));
};
}
};
}
我们来详细分析一下curry函数:
1.curry
函数首先检查传入的func
函数的参数数量(func.length
)。这个属性表示函数期望接收的参数数量。
2.如果传入柯里化函数的参数数量(args.length
)已经等于或超过了func
的参数数量,说明已经传入了足够的参数,这时curry
函数会直接调用原始函数func
,传入累积的所有参数,并返回结果。
3.如果传入的参数数量还不够,curry
函数会返回一个新的函数。这个新函数是一个闭包,它保留了对curry
函数作用域内args
数组的引用,并且能够继续接收新的参数。
4.当新的参数传入时,curried
函数会将它们添加到args
数组中。当args
数组的长度达到func
所需的参数数量时,它会调用原始函数func
。
5.为了能够正确地累积参数,curry
函数使用了concat
方法,将新传入的参数数组args2
合并到args
数组中。
通过这种方式,curry
函数能够将任意数量的参数函数转换成一系列使用一个参数的函数,从而实现柯里化:
const add = (a, b) => a + b;
const currieAadd = curry(add);
console.log(currieAadd(1)(2)); // 输出: 3