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