1、什么是函数柯里化
函数柯里化就是我们给一个函数传入一部分参数,此时就会返回一个函数来接收剩余的参数
2、简单的柯里化的实现
没有柯里化实现的案例
function sum(a,b,c){
return a+b+c
}
console.log(1,2,3) //输出结果为6
将其转化为柯里化的案例
function sum(a){
return function (b){
return function (c){
return a + b +c
}
}
}
console.log(1,2,3) //输出结果为6
简写:
const sum = a => b => c => a + b + c
console.log(1,2,3) //输出结果为6
3、函数柯里化的好处
我们希望处理函数时,希望函数功能尽可能单一。然而在实际开发中,有很多函数是多层包含并且调用的,此时用柯里化可以使需要处理的函数变得简单 如下面代码所示
function fn(a, b, c, d) {
return a + '://' + b + ':' + c + d
}
// let res = fn('http', '127.0.0.1', '80', '/a.html')
// console.log(res)
// let res1 = fn('http', '127.0.0.1', '443', '/b.html')
// console.log(res1)
// let res2 = fn('http', '127.0.0.1', '8080', '/c.html')
// console.log(res2)
// 外层函数 负责接接收参数
function currying(callback, ...arg) {
// ...arg 将后续所有实参, 以数组的形式存放在 arg 形参内, 如果没有传递的话, 是一个空数组
// console.log(callback) // 功能函数, 首次调用必传
// console.log(arg) // 基本参数, 首次调用可传可不传
// console.log(callback.length) // 函数名.length 能获取到函数的形参数量
const len = callback.length
// 内层函数负责 当前是否接受够参数了
return function (...iArg) {
iArg = [...arg, ...iArg] // 开始执行共能前, 先将两次函数调用接受的参数合并为一个数组, 后续用于计算传递的参数是否足够
if (iArg.length === len) { // 如果传递的参数数量, 刚好是功能函数需要的数量, 代表此时参数足够, 直接执行函数即可
return callback(...iArg) // 执行功能函数, 此时会得到一个拼接好的字符串, 我们将这个字符串返回出去, 就能得到功能函数的执行结果
} else { // else 分支执行时表明此时函数参数仍未接受足够, 此时需要继续接受参数, 根据函数功能, 我们应该调用 currying并将之前接收的功能函数与之前传递所有的参数全部传递进去
return currying(callback, ...iArg) // callback => 功能函数 ...iArg => 之前传递进来的所有的参数
// 这里是返回了一个 currying的调用结果, 所以相当于是返回了内层函数, 并且外层函数是接受了对应的功能函数与实际参数
}
}
}
let res = currying(fn, 'https') // 此处传递了功能函数与一个基本参数, 按照函数规则, 后续起码应该再传递够三个参数, 才能正常执行功能
let res1 = res('127.0.0.1', '80') // 此时传递了两个参数, 加上首次调用的一个参数, 现在接收到了 3个字符串, 所以应该在传递一个参数, 才能够正常执行
let str1 = res1('/a.html') // 此时传递了 一个 参数, 加上之前的三个字符串参数, 所以现在正好满足 4个参数, 所以现在就可能正常执行功能函数
console.log(str1) // https://127.0.0.1:80/a.html
let res2 = currying(fn) // 此处传递了 功能函数, 没有传递基本参数, 按照函数规则, 后续起码应该传递四个参数, 才能正常执行功能
let str2 = res2('https', 'www.baidu.com', '8080', '/a.html') // 此时传递了四个参数, 因为首次没有传递字符串, 这里就是有4个参数, 所以正常执行函数
console.log(str2) // https://www.baidu.com:8080/a.html
4、自动柯里化
function myCurried(fn) {
return function curry(...args1) {
if (args1.length >= fn.length) {
return fn.call(null, ...args1)
} else {
return function (...args2) {
return curry.apply(null, [...args1, ...args2])
}
}
}
}
function sum(a, b, c, d, e) {
return a + b + c + d + e
}
let resFunc = myCurried(sum)
console.log(resFunc(1,3,4)(1)(23))
//这里的fn.length获取的是函数传入参数的长度