🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 什么是函数柯里化 在一个函数中首先填充几个参数(然后再返回一个新函数)的技术称为柯里化(Currying)。柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果。 #### 问题 要实现一个这样的加法函数,使得: ``` add(1,2,3)(1)(2)(3)(4,5,6)(7,8)() === 42 ``` 首先,可以看到,这个函数,只有当参数为空的时候,才执行之前所有数值的加法,这样的嵌套可以无限进行,当有参数的时候,add(1,2,3),这个时候的返回值应该是一个函数,这个函数存储了1,2,3但是没有执行加法(执行了也行,此处假设就不执行,只是起到保存参数的作用),这样,继续执行add(1,2,3)(2)()就能输出1+2+3+2=8。 要实现这样的一个函数,首先,返回值在参数不为空的时候必定返回一个函数,该函数还保存了之前的参数,这就需要用到闭包。 ``` // add 函数柯里化 function add(){ //建立args,利用闭包特性,不断保存arguments var args = [].slice.call(arguments); var _add = function(){ if(arguments.length === 0){ //参数为空,对args执行加法 return args.reduce(function(a,b){return a+b}); }else { //否则,保存参数到args,返回一个函数 [].push.apply(args,arguments); return _add; } } //返回_add函数 return _add; } ``` #### 通用的函数来对普通函数进行柯里化 ``` // 通用的函数柯里化构造方法 function curry(func){ //新建args保存参数,注意,第一个参数应该是要柯里化的函数,所以args里面去掉第一个 var args = [].slice.call(arguments,1); //新建_func函数作为返回值 var _func = function(){ //参数长度为0,执行func函数,完成该函数的功能 if(arguments.length === 0){ return func.apply(this,args); }else { //否则,存储参数到闭包中,返回本函数 [].push.apply(args,arguments); return _func; } } return _func; } function add(){ return [].reduce.call(arguments,function(a,b){return a+b}); } console.log(curry(add,1,2,3)(1)(2)(3,4,5,5)(5,6,6,7,8,8)(1)(1)(1)());//69 ``` #### 题外话 实现数组扁平化:`var arr = [1,[2],[3,[4,5]],[6,[7,[8,9]]]]` * arr.toString() -> "1,2,3,4,5,6,7,8,9" * arr.flat(Infinity).toString() -> [1,2,3,4,5,6,7,8,9].toString() -> "1,2,3,4,5,6,7,8,9",其中,参数代表遍历的深度,如果是1的话,则是[1,2,3,[4,5],6,[7,[8,9]]],如果是2的话,则是[1,2,3,4,5,6,7,[8,9]]