本文旨在介绍函数式编程中柯里化的概念,以及在JavaScript中应该何时使用它。
本文将首先解释什么是柯里化,然后展示它在函数式编程背景下的用处。
什么是柯里化
柯里化是指函数永远只接受一个参数,如果需要处理多个参数,则返回另一个函数来接收单一的参数。相比之下,常规非柯里化函数可以接受多个参数。
以下是一个常规、非柯里化函数的例子:
const add = (x, y) => x + y console.log( add(2, 3) // 2 + 3 ) // prints 5
这是一个简单的函数,它接受两个参数并返回它们的和。
相同函数的柯里化版本如下所示:
const addCurried = x => y => x + y console.log( addCurried(2)(3) // 2 + 3 ) // prints 5
该函数不是接收两个参数,而是接收一个参数,然后返回另一个接收一个参数并返回两参数之和的函数。
通过这种方式,我们可以传递任意数量的参数:
const addMore = a => b => c => d => e => a + b + c + d + e console.log( addMore(1)(2)(3)(4)(5) // 1 + 2 + 3 + 4 + 5 ) // prints 15
由于柯里化函数的工作方式,我们可以进行称为部分应用的操作。部分应用是指我们向函数提供少于其可以接受的参数数量的参数:
const addCurried = x => y => x + y console.log( addCurried(2) // y => 2 + y ) // [Function (anonymous)]
如果我们仅向 addCurried 函数传递一个参数,则结果是一个,接收一个参数的函数。换句话说,数字 2 传递给了 x 参数,因此我们得到的值是 y => 2 + y。如果需要的话,我们可以将这个部分应用的函数存储到一个变量中,以便在以后复用
const addCurried = x => y => x + y const add2 = addCurried(2) // This is the same as: // const add2 = y => 2 + y console.log( add2(3) // 2 + 3 ) // prints 5 console.log( add2(10) // 2 + 10 ) // prints 12
现在我们有了一个名为 add2 的函数,它可以接收一个参数。不管我们给它传入什么参数,它都会+2 。
什么时候使用柯里化函数呢?
函数柯里化在我们的普通的函数时是没有什么优势的,他的真正优势在于组合使用,只有在组合使用时才它能真正发挥了作用。
在 JavaScript 中,组合两个函数的方式如下所示:
const compose = (f, g) => x => f(g(x)) const addCurried = x => y => x + y console.log( compose(addCurried(2), addCurried(3))(10) // 10 + 3 + 2 = 15 ) // prints 15
让我们来理解上面的操作,
- addCurried(2)=2+y,addCurried(3)=3+y
- compose(addCurried(2), addCurried(3))=2+(3+y)
- 又因为(f, g) => x => f(g(x))返回的是一个函数,这个函数接收一个参数值x
- 所以compose(addCurried(2), addCurried(3))=2+(3+y) =x =>2+(3+x)
- 又因为我又传入了一个值10
- 所以最终结果就是2+(3+10)=15