js中的柯里化函数的理解

156 阅读2分钟

在看别人写的代码的时候,总会看到这种形式的代码:
或许你会有疑问,大神就当是路过。

add(1)(2);
let add=function(x){
    return function(y){
        return x+y
    }
}
这种代码的形式相当于把平常需要传多个参数的转化为一个参数,具体有什么好处呢?
比如:
let reg1=/[a-z]/;
let str='1111';
function check(reg){
    return function (str){
        return reg.test(str)
    }
}
let hasString=check(reg1);
let hasNumber=check(/[0-9]/);

console.log(hasNumber('aaa11'))
从上面能看出来,我可以定义一个函数,多次复用。

上面的代码就是用到了柯里化的函数,说一下柯里化函数的定义,把有多个参数的函数转化为只有一个参数的函数,并且接受余下参数,有返回结果的函数。

可能对以上的概念还是有些疑惑,下面实现一个通用化的柯里化函数,无关疑惑。
在准备这一段代码之前,先了解一下js的隐式转换。toString 和valueOf
var fn=function(){
    return 1
}
console.log(fn+2);//  function(){return 1}2
fn.toString=function(){
    return 2
}
console.log(fn+2);  //4
fn.valueOf=function(){
    return 3
}
console.log(fn+2)  //5


看完这个之后,我们在了解一下闭包的概念。**函数对其状态即词法环境的引用共同构成闭包。
通俗的来讲,就是一个能访问函数外面作用域的变量的函数这个过程就是闭包。
在柯里化函数中我们会利用闭包的一个特性,内部函数可以访问外部函数的参数或变量
当把这个内部函数返回的时候,相关的变量和参数也会返回(相当于被保存在内部函数当中)**。
举例:
function add(arr){
    var waitAdd=function(){     //waiteAdd函数可以访问 arr
        return arr.reduce(function(a,b){
            return a+b
        })
    }
    return waitAdd       
}
var fn1=add([1,2,3]);
var fn2=add([1,2,3]);
、

下面实现一个通用的柯里化函数

var currys=function(fn,args){
    let length=fn.length,_this=this;   //定义一些变量
    args=args||[];   //利用闭包把每次参数都保存起来
    return function(){  //返回一个方法
        let newArg=Array.prototype.slice.call(arguments);  //定义新数组用来存参数
        Array.prototype.push.apply(newArg,args);//每次都把参数放进新数组,并且返回新数组
        if(newArg.length<length){  // 如果新数组的长度小于函数的长度,递归调用
            return currys.call(_this,fn,newArg)  //递归调用数组
        }else{
            return fn.apply(_this,newArg)  //否则直接返回
        }
    }
}
var add=function(a,b){
    return a+b
}
var newAdd=currys(add);
console.log(newAdd(1)(2)); //3

实现一个函数
add(1)(2)(3)(1) ==7;
add(1,2)(1,3) ==7;
add(1,2,3,1)==7

function add(){
    let args=Array.prototype.slice.call(arguments);
    let adder=function(){
        args.push(...arguments);
        return adder
    }
    adder.toString=function(){
        return args.reduce(function(a,b){
            return a+b
        })
    }
    return adder
}
console.log(Number(add(1,2,3,1))) // 7
console.log(Number(add(1)(2)(3)(1))) //7
console.log(Number(add(1,2)(3)(1))) //7

对于以上代码或许有疑问,可能疑问在 1、**args=args||[]; **
2、Array.prototype.slice.call(arguments)

对于1,相当于把参数每次都保存在 args里。
Array.prototype.slice == [].slice