前端 JavaScript 面试--功能整理
最编程
2024-04-11 13:07:14
...
函数柯里化 是英文 curry 直译
所谓函数柯里化,就是对函数参数控制的一种技巧
fn(1, 2, 3) 变成 fn(1)(2)(3) 依次类推,既一次传参,变成逐次传递参数
函数柯里化的作用:
- 参数复用
- 提前确认
- 延迟运行
思考,定义一个函数,add(A,B) 返回入参的和
function add(a, b){return a+b;}
如何把add柯里化,变成add(a)(b)?
- 函数add执行第一次返回一个函数 fn
- 所返回的函数fn 接受一个参数b,并且返回 a+b的值
代码示例
function curry_add(a){
return function (b){
return a+b;
}
}
如此,就实现了对add函数的柯里化
继续思考,add(a,b,c) 如何变成 add(a)(b)(c) 呢?
这样?
function curry_add(a){
return function (b){
return function (c){
return a+b+c;
}
}
}
好的,那如果是参数更多呢? 或者参数不固定呢?
如何构建一个通用形的柯里化函数?
参考上面的结果:在不确定参数多少的情况下,我们根据参数的多少,动态实现上述嵌套。
函数:function curry(fn){//接受一个函数fn,根据fn的参数长度,动态返回,上面那种嵌套的函数}
如何动态转换?
- 定义一个函数 curry() 接受一个参数fn
- curry()执行后,返回一个函数 所以,curry的框架应该是这样的
function curry(fn){
return function (){
}
}
let result = curry( (a, b)=>{return a+b } );
console.log(result(a)(b));
动态嵌套,肯定要用到递归
通过 fn的参数,来作为递归终止的条件
/*
* curry 接受一个函数,返回该函数的柯里化
* 1. 根据参数 动态实现嵌套
* 2. 函数接受一个参数
**/
function currying(func, args = []) {
let arity = func.length;
return function (..._args) {
_args.unshift(...args);
if(_args.length < arity) {
return currying(func, _args);
}
return func(..._args);
}
}
let result = currying((a, b, c)=>{
return a+b+c;
})
console.log(result(1)(2)(3))
//演进以下js执行步骤
//1. curry 执行完 -> 就得到了一个函数-> 就是result :此时 args=[] arity = 3;
//2. 此时 result(1) 执行 -> 此时 _args= [1]
//3. _args.unshift(...args) 等同于 [1].unshift([]) 应为unshift是空
//4. _args.length 明显小于 arity 继续执行curry(fn, _args); 此时args=[1] arity = 3;
//5. 此时result(2)执行 -> 此时 _args = [2]
//6. _args.unshift(...args) 等同于 [2].unshift(...[1]) 所以,_args = [1, 2];
//7. _args.length 明显小于 arity 继续执行curry(fn, _args); 此时args=[1,2] arity = 3;
//8. 此时result(3)执行 -> 此时 _args = [3]
//9. _args.unshift(...args) 等同于 [3].unshift(...[1,2]) 所以,_args = [1, 2, 3] arity=3
//10. _args.length 就不满足 小于 arity的条件
//11. 执行 函数(...args) 跳出递归了。
//更多参数时,也是上面的演变步骤。