什么是柯里化?
在数学和计算机科学中,柯里化是一种将使用多个参数的一个函数转换成一系列使用一个参数的函数的技术。
举个例子:
1 2 3 4 5 6 7
| function addFn(a,b){ return a + b } add(1,2)
let add= curriedAdd(1) add(2)
|
满足以上条件的curriedAdd 的函数可以用以下代码段实现:
1 2 3 4 5
| function curriedAdd(x){ return function(y){ return x + y } }
|
柯里化函数实现
函数柯里化的好处:参数复用。本质上是降低通用性,提高适用性。
这个curriedAdd 的实现表明了实现 Currying 的一个基础 —— Currying 延迟求值的特性
需要用到 JavaScript 中的作用域——说得更通俗一些,我们需要使用作用域来保存上一次传进来的参数
(闭包)。
对curriedAdd抽象化:
1 2 3 4 5 6 7 8 9
| function curring(fn){ var args = [].slice.call(arguments,1) return function(){ var newArgs = args.concat([].slice.call(arguments)) return fn.apply(this.newArgs) } } var addCurry = curry(add, 1); addCurry(2)
|
1 2 3 4 5 6
| function curring(fn,...args1){ return function(...args2){ fn(...args1,...args2) } }
|
以上实现也只是一个简单的curring,而且只适用于两个参数的函数。让我们用递归来实现自动Curring化。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function trueCurring(fn,args){ length = fn.length args = args || [] return function(){ var _agrs = args.slice(0), for(var i = 0;i<arguments.length;i++){ _args.push(arguments[i]) } if(_args.length < length){ return trueCurring.call(this,fn,_args) }else{ return fn.apply(this._args) } } }
|
1 2 3 4 5 6 7 8 9 10
| function trueCurring(fn,...args){ if(args.length >= fn.length){ return fn(...args) } return function(...args2){ return trueCurring(fn,...args,...args2) } }
|
实现基本思路:比较多次接受的参数总数与函数定义时的入参数量,当接受参数的数量大于或等于被 Currying 函数的传入参数数量时,就返回计算结果,否则返回一个继续接受参数的函数。
写在最后
工具库Lodsh
函数的bind方法和curring在功能上有很大的相似。