前端开发 2016-11-08
在定义柯里化、部分应用参数的概念前,首先必须对闭包有深入的了解和定义,闭包一句话说清楚:函数返回值为函数。
柯里化的定义:将多参函数分解为按步骤接受单个参数的函数,如下代码:
var mod = function(a,b){ return a * b; } function curry2(fun){ var _funTwo = function(arg){ return function(two){ return fun(arg,two); } }; return _funTwo; } var _add2 = curry2(mod); var result2 = _add2(1)(2);
mod:接受两个参数,分别为a,b;
curry2:实现柯里化功能函数,由于传入mod这个参数,返回接受一个参数的闭包;在新闭包的函数上传入另一个值(b)即可完成mod函数的执行。
var mod = function(a,b){ return a * b; } function curry2(fun){ var newVal; var _funTwo = function(arg){ return function(two){ if(!two) return newVal; newVal = fun(arg,two); return _funTwo(newVal); } }; return _funTwo; } var _add2 = curry2(mod); var result2 = _add2(1)(2)(3)(4)(5)();
a). 利用柯里化增加约束条件,只有通过所有约束条件的数据才最终被执行;
b). 变量不会存在全局污染(保护变量的私有性),自由变量(函数内部不定义,但可以访问的变量,一般情况下是全局变量,或局部全局变量),约束变量(函数内部定义的变量,生命周期在函数内部)。函数(function)依赖自由变量,就会存在自身的返回值不可控的现象,这就是传说中的共享变量耦合。
c). 无限级柯里化固能实现,但不实用,用柯里化最主要的目的是为最终执行单元增加约束条件(参数分解),约束条件是有限的。
如需要约束条件是动态的,则应该选择下面介绍的部分应用参数”
部分应用参数的定义:传入任何多个约束条件,返回接受执行单元和参数的闭包。实现约束条件的预设置。代码如下:
function Parit(fun, parg){ return function(){ var args = _.toArray(arguments); args.splice(0,0,parg); return fun.apply(fun,args); //执行后必须返回 } } function condition1(){ var validators = _.toArray(arguments); return function(fun, arg){ var errors = _.map(validators,function(data,irow){ return data(arg) ? [] : [data.name + ' error']; }); if(!_.isEmpty(errors.join())){ console.info(errors.join()); return; //throw new Error(errors.join()); } return fun.call(fun,arg); //执行后必须返回 } } var sqlPre = condition1(_.isNumber); //sqlPre是闭包,需要fun,arg两个参数 function uncheckedSqr(n){ return n * n; } console.log(sqlPre( uncheckedSqr,10) ); //本质 var sqr = Parit(sqlPre,uncheckedSqr); //返回一个闭包 uncheckedSqr作为sqlPre的第一个参数传入 console.log( sqr('5') ); console.log( sqr(5) );
a). 实现约束预设置,主要用于验证模块。
b).部分应用参数与柯里化主要区别于,柯里化每次只接受一个参数,而部分应用参数一次可以接受多个参数;但柯里化与部分应用参数都只能按照参数进行组合 。
a). 柯里化的理解是javascript进阶的基础,在函数式编程中是极其重要一环。函数式编程主要讲究数据的不变性、集合操作、尾递归等。