实现柯里化
柯里化是什么?
把接收多个参数的函数,变成接收一个单一参数(最初函数的第一个函数)的函数,并且返回接受余下的参数,而且返回的结果的新函数的技术。
如果你固定某些参数,你将得到接收余下参数的一个函数。
总结:
- 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数;
- 这个过程就称之为柯里化
例如:
function foo(m, n, x, y) {
return m + n + x + y;
}
foo(m + n + x + y)
// 柯里化过程
function bar(m) {
return function(n) {
return function (x) {
return function (y) {
return m + n + x + y;
}
}
}
}
// 调用
bar(10)(20)(30)(40)
为什么要实现柯里化?
在函数式编程中,我们希望一个函数处理的问题尽可能单一,而不是将一大堆的处理过程交给一个函数来处理;
柯里化就可以用来实现这个过程,可以将每次传入的参数在单一的函数中进行处理,处理完成后在下一个函数中再使用处理后的结果。
例如:
// 实现对错误的日志输出
/*
var log = function(date) {
return function(type) {
return function(message) {
console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]:[${message}]`)
}
}
}
*/
// 利用箭头函数进行优化
var log = date => type => message => {
console.log(`[${date.getHours()}:${date.getMinutes()}][${type}]:[${message}]`)
}
var nowlog = log(new Date())
newlog("debug")("查找到了新的bug")
newlog("info")("https请求成功")
var nowDebuglog = log(new Date())("debug")
nowDebuglog("查找到了新的bug")
nowDebuglog("首页数据获取成功")
用了柯里化后你就会发现,我们可以不必一次性得传递函数的所有参数,可以对函数进行定制化的处理。
这可以称之为函数的单一职责原则,我们可以用过柯里化的设计,在一个函数里做一件事情。
怎么实现
实现柯里化主要是用于实现以下两点:
- 柯里化后的函数可以分批接收参数。
- 柯里化的函数会生成新函数,将剩余的参数返回一个新的函数接收。
柯里化实现:
我们将要对下面这样一个函数(add)实现柯里化。
function add(num1, num2, num3) {
console.log(this, num1 + num2 + num3)
}
var curryadd = mjyCurrying(add) // mjyCurrying() 函数将模拟实现柯里化的过程
curryadd(10, 20, 30) // 一次性接收全部参数
curryadd.call('111',10, 20, 30) // 可以通过call改变this指向
curryadd(10)(20)(30) // 分批接收参数
curryadd(10)(20,30) // 分批接收参数
mjyCurrying 函数通过递归实现模拟柯里化过程
function mjyCurrying(fn) {
function curried(...args) {
// 如果参数第一步就传递够了
if ( args.length >= fn.length ) {
// 有可能在调用的时候需要改变this指向,我们这里用进行this的绑定
return fn.call(this, ...args)
} else {
// 参数不够,需要返回一个新的参数,继续来接收剩余的参数(对curried进行回调)
function callback_curried(...args2) {
return curried.call(this, ...args, ...args2)
}
return callback_curried
}
}
return curried
}