一、概念
函数柯里化就是将一个需要传入多个参数的函数改写成传入一个或多个参数,然后返回需要传入剩余参数的函数。
比如计算参数之和。
正常函数:接收所有参数,返回的是一个值(和)。属于一锤子买卖。
柯里化函数:接收部分参数,返回的是一个函数,可以使用剩余参数继续调用该函数,以得到最终的值(和)。属于分布式买卖。
二、案例
看一个很简单的例子。
//没有柯里化
function reduce(a,b,c){
return a-b-c;
};
console.log(reduce(3,2,1))// 0
//函数柯里化
function reduce(a){
return function(b){
return function(c){
return a-b-c;
};
};
};
console.log(reduce(3)(2)(1))// 0
三、为什么使用函数柯里化
既然传一次参数就能解决的问题,为什么要分多次传昵?主要有以下几个方面的原因。
1.函数复用
柯里化谐音有点像颗粒化,这跟通常所理解的模块化有异曲同工之妙,最主要的作用就是实现函数的复用,可以用一个变量接收第一个方法的调用,第一个方法就被独立化了,那么其他地方也可以调用。这也符合通常所说的“低耦合”。
例:
//求任何数的百分数
function base(radix) {
return function (param) {
return param/radix+'%';
}
};
var radix = base(100);
//可以实现radix方法的复用
console.log(radix(100));
console.log(radix(50));
2.延迟执行
call() 方法与 bind() 方法的区别就在于 bind 是调用的时候执行,而 call 是自执行。所以 bind 就是一种函数柯里化的运用。
例:
Function.prototype.myBind = function (o) {
//获取调用函数
var _this = this;
//获取第一次调用时的参数
var param = Array.prototype.slice.call(arguments);
param.shift();
return function(){
//获取第二次调用时的参数
var param2 = Array.prototype.slice.call(arguments);
return _this.apply(o,[...param,...param2])
}
}
四、面试题
// 写出add方法,使等式成立:
add(1)(2)(3) = 6;
add(1, 2, 3)(4) = 10;
add(1)(2)(3)(4)(5) = 15;
//求和方法
function total(a,b){
return a+b;
}
//方法如下
function add(...param) {
//使用递归将所有函数数组通过整合
var fn = function (...arg) {
param = [...param,...arg];
return fn;
};
//最后执行的时候重写toString方法,返回参数数组的和
fn.toString = function () {
//使用reduce函数求和
return param.reduce(total);
};
return fn;
}
console.log(add(1,2,3)(4));//10
console.log(add(1)(2)(3));//6
console.log(add(1)(2)(3)(4)(5));//15