柯里化
定义:柯里化是这么一个函数,他接收一个函数 A 为参数,运行后能够返回一个新函数,这个新函数能够处理函数 A 的剩余参数。
配合例子理解这个定义
假如有个一接收三个参数的函数 A
1 | function A(a, b, c) { |
同时还要一个封装好的柯里化通用函数 createCurry 。他接收 A 为参数,能够将 A 转化为柯里化函数,返回结果就是这个转化之后的函数。
1 | var _A = createCurry(A); |
那么 _A 作为 createCurry 运行的返回函数,他能够处理 A 的剩余参数。因此下面的执行结果是等价的。
1 | _A(1, 2, 3); |
_A 能够处理 A 的所有剩余参数。因为柯里化也可以被称为部分求值。
在简单的场景下,可以不借用柯里化通用式得到柯里化函数,比如一个简单的加法函数
1 | function add(a, b, c) { |
柯里化的实现思路:
柯里化函数的运行过程其实是一个参数的收集过程,每次将传入的参数收集起来,在最里层处理。
1 | // arity 用于标记剩余参数的个数 |
柯里化确实把简单的问题复杂化了,但复杂化的同时,我们在使用函数时拥有了更多的自由度。也就是说,柯里化的核心,就是对于函数参数的自由处理。
举一个非常常见的例子
验证一串数字是否是正确的手机号,按照普通的思路,可能如下封装
1 | function checkPhone(phoneNumber) { |
如果想要验证一个邮箱,可能如下封装
1 | function checkEmail(email) { |
除此之外,可能还有更多的封装逻辑,因此在实践中,为了统一逻辑,我们会封装一个更为通用的函数
1 | function check(reg, targetString) { |
但是这样封装之后,在使用时又会稍微麻烦一点,因为总是输入一串正则,这样就导致使用效率低下,并且容易出错
1 | check(/^1[34578]\d{9}$/, '14900000088'); |
那么这个时候,我们可以借助柯里化,在 check 的基础上,再做一层封装,以简化使用
1 | var _check = createCurry(check); |
最后在使用的时候就会变得更加直观与简洁了
1 | checkPhone('183888888'); |
通过这个例子可以发现,柯里化能够应付更加复杂的逻辑封装。
虽然柯里化确实在一定程度上将问题复杂化了,也让代码更加不容易理解。但是柯里化在面对复杂情况下的灵活性却让我们不得不爱。