什么是函数的柯理化?
柯里化(Currying)是把多个参数的函数变换成单一参数的函数
柯理化可以对函数参数进行缓存
//柯理化示例
const _ = require('lodash')
function getSum (a, b, c) {
return a + b + c
}
const curried = _.curry(getSum)
console.log(curried(1, 2, 3)) // 6
console.log(curried(1)(2, 3)) // 6
console.log(curried(1, 2)(3)) // 6
//柯理化示例
const _ = require('lodash')
function getSum (a, b, c) {
return a + b + c
}
const curried = _.curry(getSum)
console.log(curried(1, 2, 3)) // 6
console.log(curried(1)(2, 3)) // 6
console.log(curried(1, 2)(3)) // 6
柯理化的模拟实现
// 写法一:
function curry(fn) {
function _c(restNum, argsList) {
return restNum === 0 ?
// fn.apply(null, argsList)
fn.apply(null, argsList) :
function(x) {
return _c(restNum - 1, argsList.concat(x));
};
}
return _c(fn.length, []);
}
// 使用
var plus = curry(function(a, b) {
return a + b;
});
// 3
console.log(plus(1)(2));
// 写法一:
function curry(fn) {
function _c(restNum, argsList) {
return restNum === 0 ?
// fn.apply(null, argsList)
fn.apply(null, argsList) :
function(x) {
return _c(restNum - 1, argsList.concat(x));
};
}
return _c(fn.length, []);
}
// 使用
var plus = curry(function(a, b) {
return a + b;
});
// 3
console.log(plus(1)(2));
入参出参:调用传递一个纯函数的参数,完成之后返回一个柯里化函数
入参情况分析:
如果curried调用传递的参数和getSum函数参数个数相同,那么立即执行并返回调用结果
如果curried调用传递的参数是getSum函数的部分参数,那么需要返回一个新的函数,并且等待接收getSum的其他参数
重点关注:
获取调用的参数
判断个数是否相同
// 写法二:模拟柯里化函数
function curry (func) {
// 取名字是为了下面实参小于形参的时候用的
return function curriedFn(...args) {
// 判断实参和形参的个数
if(args.length < func.length) {
return function() {
// 等待传递的剩余参数,如果剩余函数的参数加上之前的参数等于形参,那么就返回func
// 第一部分参数在args里面,第二部分参数在arguments里面,要将两个合并并且展开传递(使用...)
// concat函数要合并两个数组,arguments为伪数组,所以用Array.from进行转换
return curriedFn(...args.concat(Array.from(arguments)))
}
}
// 如果实参大于等于形参的个数
// args是剩余参数,是个数组形式,而返回的时候要展开(使用...)
return func(...args)
}
}
// test
const curriedTest = curry(getSum)
console.log(curriedTest(1, 2, 3)) // 6
console.log(curriedTest(1)(2, 3)) // 6
console.log(curriedTest(1, 2)(3)) // 6
// 写法二:模拟柯里化函数
function curry (func) {
// 取名字是为了下面实参小于形参的时候用的
return function curriedFn(...args) {
// 判断实参和形参的个数
if(args.length < func.length) {
return function() {
// 等待传递的剩余参数,如果剩余函数的参数加上之前的参数等于形参,那么就返回func
// 第一部分参数在args里面,第二部分参数在arguments里面,要将两个合并并且展开传递(使用...)
// concat函数要合并两个数组,arguments为伪数组,所以用Array.from进行转换
return curriedFn(...args.concat(Array.from(arguments)))
}
}
// 如果实参大于等于形参的个数
// args是剩余参数,是个数组形式,而返回的时候要展开(使用...)
return func(...args)
}
}
// test
const curriedTest = curry(getSum)
console.log(curriedTest(1, 2, 3)) // 6
console.log(curriedTest(1)(2, 3)) // 6
console.log(curriedTest(1, 2)(3)) // 6