函数式编程在把函数当作一等公民的同时,就不可避免的会产生“柯里化”这种用法。 函数柯里化是逐步传参,逐步缩小函数的适用范围,逐步求解的过程。
1 2 3 4 5 6 7 8 9 10 11 var currying = function (fn ) { var _args = []; return function _fn (...args ) { if (args.length === 0 ) return fn.apply(this , _args); _args.push(...args); return _fn; }; };
推迟计算 柯里化可以推迟计算,需要的时候再去求值。比如一家店要计算每月的盈利,首先要记录每天的盈利,这个就可以使用柯里化函数去解决。
1 2 3 4 5 6 var multi = (...args ) => args.reduce((total, cur ) => total + cur, 0 );var sum = currying(multi);sum(100 , 200 )(300 ); sum(400 ); console .log(sum()); console .log(sum(3 )(30 )(300 )());
复用参数 柯里化还可以复用参数。比如五千元买入不同的股票,计算三个月后各自的总价值。实现参数复用只需要将 curring 函数修改一行代码。
1 2 3 4 5 6 7 8 var currying2 = function (fn ) { var _args = [].slice.call(arguments , 1 ); return function ( ) { if (arguments .length === 0 ) return fn.apply(this , _args); [].push.apply(_args, [].slice.call(arguments )); return arguments .callee; }; };
1 2 3 var sum2 = currying2(multi, 5000 ); console .log(sum2(45 , 33 , 90 )()); console .log(sum2(13 , 40 , 120 )());
提前返回 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 var addEvent = function (el, type, fn, capture ) { if (window .addEventListener) { el.addEventListener( type, function (e ) { fn.call(el, e); }, capture ); } else if (window .attachEvent) { el.attachEvent("on" + type, function (e ) { fn.call(el, e); }); } };
以上代码,我们每次使用addEvent
为元素添加事件的时候,IE6/IE7
都会走一遍if...else if...
,其实使用柯里化只要一次判定就可以了,如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 var addEvent = (function ( ) { if (window .addEventListener) { return function (el, sType, fn, capture ) { el.addEventListener( sType, function (e ) { fn.call(el, e); }, capture ); }; } else if (window .attachEvent) { return function (el, sType, fn, capture ) { el.attachEvent("on" + sType, function (e ) { fn.call(el, e); }); }; } })();
不定参数柯里化 文章头部的currying
函数已经是不定参数的柯里化了,但是最后需要执行()
才能结束
现在希望实现如下效果
此时的柯里化函数应该如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function curry (fn ) { const presetArgs = [].slice.call(arguments , 1 ) function curried ( ) { const restArgs = [].slice.call(arguments ) const allArgs = [...presetArgs, ...restArgs] return curry.call(null , fn, ...allArgs) } curried.toString = function ( ) { return fn.apply(null , presetArgs) } return curried; }
通过改写函数的toString
方法,使得结果函数可以被Javascript引擎解析,得到一个预期的值。