什么是函数的柯里化?
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。
哪里用到了柯里化函数?
Lodash.js这个js库中就有提供如何把一个函数柯里化
const _ = require('lodash');//node环境
const sum = (n1,n2,n3,n4)=>n1 + n2 + n3 + n4;
//lodash中的curry函数,传入需要进行柯里化的函数,返回一个被柯里化的函数
const curriedSum = _.curry(sum);
console.log(curriedSum(1,2,3,4));
console.log(curriedSum(1)(2)(3)(4));
console.log(curriedSum(1,2)(3,4));
console.log(curriedSum(1)(2,3)(4));
运行结果
如何模仿lodash中的curry这个函数
//myCurry
/**
*
* @param {*} fn 需要被柯里化的函数
* @args 不定参数,myCurry返回的函数被调用时所接收的参数
* @returns
*/
const myCurry = function(fn){
return function mid(...args){
if(fn.length > args.length){
return function(){
return mid(...[...args,...Array.from(arguments)]);//缓存前面函数调用中的参数
}
}
return fn(...args);
}
}
const curriedSum = myCurry(sum);
console.log(curriedSum(1,2,3,4));
console.log(curriedSum(1)(2)(3)(4));
console.log(curriedSum(1,2)(3)(4));
console.log(curriedSum(1,2)(3,4));
运行结果
那么如何解决add(1)(2,3)(4)()这个问题呢?
const add = function(...args1){
return function(...args2){
let args = [...args1,...args2];//参数合并
if(args2.length === 0){//add(1,2,3)(4)()最后一次调用的时候是没有传递参数的,通过参数判断是否要求和
total = 0;
for(let i = 0;i<args.length;i++){
total += args[i];
}
return total;
}else{
return add(...args);//调用add拿到之前的参数
}
}
}
console.log(add(1,2,3,4)());
console.log(add(1)(2)(3)(4)());
console.log(add(1,2)(3)(4)());
console.log(add(1)(2,3)(4)());
上面的两个案例都用了高阶函数,闭包,高阶函数可以是函数变得更加灵活,而闭包则可以缓存数据,缺点就是可能造成栈溢出,所以在平时的代码中需要自己取舍。