偏函数与函数柯里化

偏函数与函数柯里化

1. 偏函数

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

1. 工厂方法

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

1
2
3
4
5
6
7
8
9
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 方法封装成偏函数的形式来实现更加简洁的代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 入参函数
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 方法来实现偏函数

1
2
3
4
5
6
7
8
9
10
11
function add(a, b) {
return a + b;
}

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

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

2. 函数柯里化

柯里化是另一个有趣的处理函数技术。

柯里化(Currying):转换一个调用函数f(a,b,c)为f(a)(b)(c)方式调用。

下面实现了一个柯里化函数,执行一个两元参数函数,即转换f(a,b)至f(a)(b):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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. 无限加参

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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);