柯里化是指这样的一个函数(假设叫做createCurry),它接收函数A作为参数,运行后能够返回一个新的函数,并且这个新的函数能够处理函数A的剩余参数。
例如,有一个简单的加法函数,它能够将自身的三个参数加起来并返回计算结果。
function add(a, b, c) {
return a + b + c
}
add函数的柯里化函数_add可以写成:
function _add(a) {
return function (b) {
return function (c) {
return a + b + c
}
}
}
因此下面两个运算方式是等价的。
add(1, 2, 3)
_add(1)(2)(3)
在这里我们可以看出,柯里化函数的运行过程其实是一个收集参数的过程,我们将每一次传入的参数收集起来,并在最里层进行处理,实现createCurry时可以借助此思路来封装
再举个例子:
如果要验证手机号码和邮箱一般的思路如下:
function checkPhone(phoneNum) {
return /^1[345678]\d{9}$/.test(phoneNum)
}
function checkEmail(email) {
return /^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/.test(email)
}
如果还需要验证的东西更多的话,我们一般会选择封装一个通用方法,将正则和需要验证字段传进去:
function check(reg, targetString) {
return reg.test(targetString)
}
check(/^1[345678]\d{9}$/, '13333333333')
check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, 'test@123.com')
这样会遇到其他问题,因为总需要输入一串正则,导致效率低下。
这个时候,就可以借助柯里化,在check的基础上再做一层封装,以简化使用。
let _check = createCurry(check)
let checkPhone = _check(/^1[345678]\d{9}$/)
let checkEmail = _check(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/)
checkPhone('13333333333')
checkEmail('xxxx@123.com')
柯里化能够应付更加复杂的逻辑封装。当情况变得多变时,柯里化依然能够应付自如。虽然柯里化一定程度上将问题复杂化,也让代码变的更加不容易理解,但是柯里化再面对复杂情况时灵活性让人不得不爱。
柯里化函数通常由以下步骤动态创建:调用另一个函数并为它传入要柯里化的函数和必要参数。下面是创建柯里化函数的通用方式:
function curry(fn) {
var args = Array.prototype.slice.call(argumnets, 1)
return function() {
var innerArgs = Array.prototype.slice.call(arguments)
var finalArgs = args.concat(innerArgs)
return fn.apply(null, finalArgs)
}
}