路漫漫其修远兮
头像

codermjy

A programmer who subconsciously views himself as an artist

will enjoy what he does and will do it better

实现柯里化

柯里化是什么?

把接收多个参数的函数,变成接收一个单一参数(最初函数的第一个函数)的函数,并且返回接受余下的参数,而且返回的结果的新函数的技术。

如果你固定某些参数,你将得到接收余下参数的一个函数。

总结:

  • 只传递给函数一部分参数来调用它,让它返回一个函数去处理剩余的参数;
  • 这个过程就称之为柯里化

例如:

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
}
posted @ 2022-05-29 11:08  不愿染是与非  阅读(84)  评论(0编辑  收藏  举报