作家
登录

javascript currying返回函数的函数

作者: 来源:www.28hudong.com 2013-03-30 02:10:26 阅读 我要评论

最早期的curry函数有点多态的意味,就是根据函数参数在内部选用分支: 复制代码 代码如下: //http://www.openlaszlo.org/pipermail/laszlo-user/2005-March/000350.html // ★★On 8 Mar 2005, at 00:06, Steve Albin wrote: function add(a, b) { if (arguments.length < 1) { return add; } else if (arguments.length < 2) { return function(c) { return a + c } } else { return a + b; } } var myadd = add( 2 ); var total = myadd(3); 日本的一个先行者可能在未搞清arguments也能用Array的原生方法转换为数组的时候,用非常复杂的正则与eval搞出一个更接近现代currying意味的函数。 复制代码 代码如下: function curry(fun) { if (typeof fun != 'function') { throw new Error("The argument must be a function."); } if (fun.arity == 0) { throw new Error("The function must have more than one argument."); } var funText = fun.toString(); var args = /function .*((.*))(.*)/.exec(funText)[1].split(', '); var firstArg = args.shift(); var restArgs = args.join(', '); var body = funText.replace(/function .*(.*) /, ""); var curriedText = "function (" + firstArg + ") {" + "return function (" + restArgs + ")" + body + "}"; eval("var curried =" + curriedText); return curried; } function curry(fun) { if (typeof fun != 'function') { throw new Error("The argument must be a function."); } if (fun.arity == 0) { throw new Error("The function must have more than one argument."); } var funText = fun.toString(); var args = /function .*((.*))(.*)/.exec(funText)[1].split(', '); var firstArg = args.shift(); var restArgs = args.join(', '); var body = funText.replace(/function .*(.*) /, ""); var curriedText = "function (" + firstArg + ") {" + "return function (" + restArgs + ")" + body + "}"; eval("var curried =" + curriedText); return curried; } function sum(x, y) { return x + y; } function mean3(a, b, c) { return (a + b + c)/3; } var a = curry(sum)(10)(15) alert(a)//25 var b = curry(mean3)(10)(20, 30); alert(b)//20 var c = curry(curry(sum))(10)()(20); alert(c); var d = curry(curry(mean3)(10))(20)(30); alert(d); [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 接着是闭包的流行,与数组转换arguments的技术的发现,现代currying函数终于粉墨登场,就好像15~17世纪大航海时代的地理大发现,javascript的世界突然间开阔了许多。 复制代码 代码如下: //一个简单的现代currying函数 function curry (fn, scope) { var scope = scope || window; var args = []; for (var i=2, len = arguments.length; i < len; ++i) { args.push(arguments[i]); }; return function() { fn.apply(scope, args); }; } 一般的currying函数只有两重,执行情况如下,第一次执行参数不足返回内部函数,第二次执行才最终完成。不过针对这参数,我们还是可以做一些文章。看如下函数: 复制代码 代码如下: function sum(){ var result=0; for(var i=0, n=arguments.length; i<n; i++){ result += arguments[i]; } return result; } alert(sum(1,2,3,4,5)); // 15 这就没有所谓的参数不足问题,传入一个参数,它也计算。但不传入参数呢?无错,区别在于有没有参数。我们可以让它不断执行自身,如果参数存在的情况下。最后在没有参数的情况下,一次过执行。换言之,前面的步骤是用于储存参数。 var sum2= curry(sum); sum2= sum2(1)(2)(3)(4)(5); sum2(); // 15 比起一般的currying函数,这有点难度。具体看注解: 复制代码 代码如下: var curry= function(fn){//原函数的参数为函数 return function(args){//内部函数的参数为数组,由于立即执行,因此直接到第三重去 //args是相对于第三重内部函数可是全局变量 var self= arguments.callee;//把自身保存起来(就是那个数组为参数的第二重函数) return function(){ //这才是第二次调用的函数 if(arguments.length){//如果还有要添加的参数 [].push.apply(args,arguments);//apply把当前传入的所有参数放进args中 return self(args); }else{ return fn.apply(this,args);//apply的第二参数为数组 } } }([]); }; function sum(){ var result=0; for(var i=0, n=arguments.length; i [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]或者每次传入多个参数: function sum(){ var result=0; for(var i=0, n=arguments.length; i [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行] 但上面的函数有不足之处,最后怎么也要放个括号,我们想只要参数足够就返回结果,多出的参数忽略。改进如下: 复制代码 代码如下: function curry(f) { if (f.length == 0) return f; function iterate(args) { if (args.length <= f.length) return f.apply(null, args); return function () { return iterate(args.concat(Array.prototype.slice.call(arguments))); }; } return iterate([]); } function curry(f) { if (f.length == 0) return f; function iterate(args) { if (args.length >= f.length) return f.apply(null, args); return function () { return iterate(args.concat(Array.prototype.slice.call(arguments))); }; } return iterate([]); } function mean3(a, b, c) { return (a + b + c) / 3; } var curriedMean3 = curry(mean3); alert(curriedMean3(1)(2, 3)); // => 2 alert(curriedMean3(1)(2)(3));//空括号无效 alert(curriedMean3()(1)()(2)()(3)); // => 2 alert(curriedMean3(1, 2)(3, 4)); // => 2 (第四个参数无效) [Ctrl+A 全选 注:如需引入外部Js需刷新才能执行]

  推荐阅读

  CSS+Js遮罩效果的TAB及焦点图片切换(推荐)

Js遮罩效果的TAB及图片切换 div, ul, ol, li, dl, dt, dd { margin:0; padding:0; } .imgFlash,.tab{margin:auto} /*------焦点图片的css-------*/ .imgFlash { height:230px;width:270px; po>>>详细阅读


本文标题:javascript currying返回函数的函数

地址:http://www.17bianji.com/kaifa2/JS/27748.html

关键词: 探索发现

乐购科技部分新闻及文章转载自互联网,供读者交流和学习,若有涉及作者版权等问题请及时与我们联系,以便更正、删除或按规定办理。感谢所有提供资讯的网站,欢迎各类媒体与乐购科技进行文章共享合作。

网友点评
自媒体专栏

评论

热度

精彩导读
栏目ID=71的表不存在(操作类型=0)