学了一天,人都麻了。。。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>柯里化函数</title>
</head>
<body>
<script>
//一个函数需要传入多个参数,现在把这个函数进行柯里化,
// 新的函数允许可以接收单个参数或多个参数,链式调用进行最终的函数执行
//简单的例子
function add(a,b,c){
return a+b+c
}
//柯里化后的函数
function curriedAdd(a){
return function (b){
return function(c){
return a+b+c
}
}
}
const res = curriedAdd(1)(2)(3)
console.log(res);
//步骤分解:
//第一次调用返回一个函数
const step1 = curriedAdd(1)
//第二次调用返回一个函数
const step2 = step1(2)
//第三次调用返回结果
const resC = step2(3)//数据是通过闭包保存下来的,所以里面的函数能用。
console.log(resC);
//原本需要一次传递三个参数,现在只需一个一个传递了,但是最后还是执行的原函数的代码
//通用的柯里化函数,将一个函数转成柯里化函数
function curry(fn){
return function curried(...args){
//柯里化函数,核心逻辑
if(args.length >= fn.length){//参数够了直接执行当前函数并返回
return fn.apply(this,args)
}else{//参数不够,将参数逐一添加进去,返回新的函数,函数的返回值是执行本回调函数的结果
return function (...args2){
return curried.apply(this,args.concat(args2))
}
}
}
}
const curriedNew = curry(add)
const resNew = curriedNew(1)(2)(3)
console.log(resNew);
//步骤拆解:
//curriedNew 是一个柯里化的函数
//curriedNew(1)
//add的参数大于传来的长度,走else
//返回一个函数记录为steps1
//const steps1 = function (...args2){
// return curried.apply(this,args.concat(args2)) 此时args为[1],闭包记住了
// }
//然后curriedNew(1)(2)等价于steps1(2)
//返回curried.apply(this,args.concat(args2))的执行结果,此时[1,2]
//add的参数还是大于传来的长度,返回一个函数记录为steps2
// const steps2 = function (...args2){
// return curried.apply(this,args.concat(args2))//此时的args为[1,2]
// }
//最后curriedNew(1)(2)(3)等价于steps2(3)
//返回curried.apply(this,args.concat(args2))的执行结果,此时后面为[1,2,3]
//递归发现长度相等了,就返回:执行fn.apply(this,args)此时args为[1,2,3]执行原来的函数。
//最终返回a+b+c
const resNews = curriedNew(1,2)(3)
console.log(resNews);
//第一步返回一个柯里化的函数curriedNew
//curriedNew(1,2)
//传来的参数数量小于原函数所需的参数,走else
//返回一个函数
// function (...args2){
// return curried.apply(this,args.concat(args2))此时的args为[1,2],闭包在记录着
// }
//然后curriedNew(1,2)(3)
//返回curried.apply(this,args.concat(args2))的执行结果,此时后面这部分的值为[1,2,3]
// 然后递归调用发现参数数量相等,然后走上面的分支
// 返回curried.apply(this,args.concat(args2))执行结果,就是1+2+3
//为什么使用>=号?
function aa(a,b,c){
return a+b+c
}
console.log(aa(1,2,3,4));//正常会忽略4的
//避免传过来的值过多而出现逻辑错误。可以接收多余参数。
</script>
</body>
</html>