函数柯里化
柯里化(Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参 数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。
找找感觉
下面有计算两个数之后的两种写法,
// 普通函数
function add(x, y) {
return x + y;
}
// 函数调用
add(1, 2) // 3
暗藏柯里化思想的写法
// 柯里化之后
function addX(y) {
return function (x) {
return x + y;
};
}
addX(2)(1) // 3
当然,上面的代码并不具备通用性,下面看一个更复杂的例子。
手写一个柯里化函数
目标: 把下面的代码补全,并能通过如下的测试用例。
function curry () {
// 你的代码
}
function sum(a, b, c) {
console.log(a + b + c);
}
const fn = curry(sum);
// 测试用例
fn(1, 2, 3); // 6
fn(1, 2)(3); // 6
fn(1)(2, 3); // 6
fn(1)(2)(3); // 6
柯里化的通用实现
最核心的思路:
- 接收一部分参数,返回一个函数接收剩余参数
- 接收足够参数后,执行原函数
背景知识:通过函数的 length 属性,可获取函数的形参个数
参考答案
// func 要做柯里化处理的函数;
// curArg 用来统一接收实参的数组,这里用到了默认值,并构成一个闭包结构
function curry (func,curArg=[]) {
return function (...arg) {
arg = curArg.concat(arg)
if(arg.length >= func.length) { // 收到的参数个数够了没有
return func.apply(null,arg)
} else {
return curry(func,arg)
}
}
}
柯里化的取舍
- 柯里化把事情搞复杂了。对于函数fn,本来可以直接传入所有的值进行求解,而经过柯里化之后,要逐步传入参数,逐步求解。
- 柯里化把让函数更加灵活。 举个判断数据类型的例子来验证下
// 定义函数
function checkType(type,value) {
return Object.prototype.toString.call(value) === `[object ${type}]`;
}
// 测试功能
console.log(checkType('Array',[])) // true
从这个函数出发,可以用柯里化得到更多的功能函数
const isArray = curry(checkType,['Array']) // 从checkType得到了新函数isArray
const isFucntion = curry(checkType,['Function'])
// 测试使用
isArray([])
isFucntion(()=>{})