Skip to main content

偏函数与函数柯里化

一、偏函数

所谓偏函数,就是固定一个函数的一个或者多个参数,返回一个新的函数,这个函数用于接受剩余的参数。

1. 工厂方法

首先来看一个简单的例子:

function add(a, b) {
return a + b;
}

add(1, 2);
add(1, 3);
add(1, 4);
add(1, 5);
add(1, 6);

我们发现,调用 add 方法时,第一个参数相同,但是我们写了 5 遍,鉴于此种情况,我们可以将 add 方法封装成偏函数的形式来实现更加简洁的代码。

// 入参函数
function add(a, b) {
return a + b;
}

// 生产偏函数的工厂
function partial(fn, a) {
return function (b) {
return fn(a, b);
};
}

// 得到偏函数
var parAdd = partial(add, 1);

parAdd(2);
parAdd(3);
parAdd(4);
parAdd(5);
parAdd(6);

由上边我们可以看到,偏函数也利用了闭包的原理。

2. bind 方法

由于 bind 函数会返回一个未执行的新函数,且新函数与被调函数具有相同的函数体,所以我们也可以使用 bind 方法来实现偏函数

function add(a, b) {
return a + b;
}

var parAdd = add.bind(null, 1);

parAdd(2);
parAdd(3);
parAdd(4);
parAdd(5);
parAdd(6);

二、函数柯里化

柯里化是另一个有趣的处理函数技术。柯里化(Currying):转换一个调用函数 f(a,b,c)为 f(a)(b)(c)方式调用。下面实现了一个柯里化函数,执行一个两元参数函数,即转换 f(a,b)至 f(a)(b):

function add(a, b) {
return a + b;
}

function curry(fn) {
return function (a) {
return function (b) {
return fn(a, b);
};
};
}

var carriedSum = curry(add);

carriedSum(1)(2);
  • curry(func)的结果是 function(a)的一个包装器。
  • 当调用 sum(1)是,参数被保存在词法环境中,然后返回新的包装器 function(b)
  • 然后 sum(1)(2)提供 2 并最终调用 function(b),然后传递调用给原始多参数函数 sum。

1. 无限加参

function add(...args) {
var result = 0;

if (args.length > 0) {
for (var i = 0; i < args.length; i++) {
result += args[i];
}
}

return result;
}

function curry(fn, ...args) {
var all = args || [];

return function (...rest) {
all.push(...rest);
if (rest.length == 0) {
return fn.apply(null, all);
} else {
return curry.call(null, fn, ...all);
}
};
}

var add2 = curry(add);

var cc = add2(1)(3)();

console.log(cc);