js函数柯里化

149 阅读2分钟

发个牢骚:被大厦的物业和公司的领导坑了一波。昨天早上公司所在的大楼因为疑似新冠被封了一个半小时,然后大厦把门打开,建议我们居家办公。公司领导整了一个神操作,叫我们上午在家办公,下午去公司继续上班。然后下午大楼里就确诊了一个。现在人已经被隔离在公司出不去了。被隔离的第一晚,在同事的呼噜声中醒来。。。

柯里化

柯里化(currying)又称部分求值。一个currying的函数首先会接受一些参数,但是该函数不会立即求值,而是返回一个函数,然后将传入的参数以闭包的方式存起来。在真正想要求值的时候,再进行求值。我们先来看一个简单的例子,虽然这个例子不是最完整的currying,但是我们先从简单的开始:

function addCurrying() {
	var nums = [] //这是用来存参数的数组
	//求和函数
	function add(arr) {
		return arr.reduce((total, currentValue) => total + currentValue, 0)
	}
        //返回一个函数
	return function() {
		if (arguments.length) {
			//如果有参数传进来。那么就不进行求值,将传入的参数保存在闭包里面
			nums.push(...arguments)
		} else {
			//没有参数传进来就求值
			return add(nums)
		}
	}

}
var addFn = addCurrying()
addFn(100); //未真正求值
addFn(1000); //未真正求值
addFn(); //真正求值了

我们来解释一下以上代码:首先我们定义了一个函数,在函数的内部有一个变量nums,一个有求和功能的函数。函数的返回值是一个函数,在返回的函数中我们有用到nums这个变量,这就形成了一个闭包的结构,意味着nums不会被垃圾回收机制回收,里面存的数据就是我们外部传入的参数。然后在返回的函数中我们定义了执行求和函数(add)的条件,在有参数传进来的时候不进行求值而是把参数保存起来,没有参数传进来的时候才进行求值。

接下来我们编写一个通用的currying的函数,这个函数接收一个参数,即要被currying的函数,这个函数的作用可能就不像add这样单一,你可以随意传入一个想要被currying的函数:

function currying(fn) {
  var args = []
  return function() {
  	if (arguments.length) {
  	  args.push(...arguments)
  	  return arguments.callee
  	} else {
  		return fn.call(this, ...args)
  	}
  }
 }
function add() {
  var arr=[...arguments]
  return arr.reduce((total, currentValue) => total + currentValue)
}
var curAdd = currying(add)
console.log(curAdd(10))
console.log(curAdd(100)(300))
console.log(curAdd())

以上