柯里化

什么是柯里化

柯里化可以说是一种函数式编程的过程,其主要目的就是把多个参数的函数转换成一个只接受一个单一参数的函数。被柯里化的函数会返回一个新的函数并接受新的一个参数
在所有的参数用完之后,它才会去执行得到最后的结果

实现柯里化

一个常见又简单的例子

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

通过闭包的形式把新的函数 return 出来,这种方式一看就懂,但是如果一开始不知道参数数量就没法这么写了,所以我们可以改写成这样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function curry(func) {
var args = [].slice.call(arguments, 1)
//新建_func函数作为返回值
var _func = function() {
//参数长度为0,执行func函数,完成该函数的功能
if (arguments.length === 0) {
return func.apply(this, args)
} else {
//否则,存储参数到闭包中,返回本函数
[].push.apply(args, arguments)
return _func
}
}
return _func
}

解释一下这个函数,argments 中保存着函数的参数,.length 方法可以获取到参数个数,当还有剩余参数的时候,就把参数合并,返回新函数,如果参数填入完整就调用。

一个更加简洁的版本

1
2
3
4
5
6
const curry = fn => {
if (fn.length <= 1) return fn
const generator = args =>
args.length === fn.length ? fn(...args) : arg => generator([...args, arg])
return generator([], fn.length)
}

作用

这是一个计算商品价格的函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function discount(price, discount) {
return price * discount
}

const price = discount(500, 0.1) // $50
// $500 - $50 = $450
const price = discount(1500, 0.1) // $150
// $1,500 - $150 = $1,350
const price = discount(2000, 0.1) // $200
// $2,000 - $200 = $1,800
const price = discount(50, 0.1) // $5
// $50 - $5 = $45
const price = discount(5000, 0.1) // $500
// $5,000 - $500 = $4,500
const price = discount(300, 0.1) // $30
// $300 - $30 = $270

其实折扣力度都一样,变化的只是原价格,我们利用 curry 改写一下

1
2
3
4
5
6
fucntion price(discount){
return function(price){
return discount*price
}
}
const tenPercentDiscount = discount(0.1);

这下我们只用输入价格就 ok 了