对柯里化函数理解
curring 的代码解析
代码出自书籍《JavaScript设计模式与开发模式》。
在这之前我大概介绍下什么是 函数柯里化。
currying 又称为部分求值。一个 currying 的函数首先会接受一些参数,接受了这些参数之后, 该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包中被保 存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。(摘自《JavaScript设计模式与开发模式》)
var currying = function( fn ){
var args = [];
return function(){
if ( arguments.length === 0 ){
return fn.apply( this, args );
}else{
[].push.apply( args, arguments );
//使用了apply,其实相当于 args.push(arguments[0], arguments[1],...);
return arguments.callee;
}
}
};
var cost = (function(){
var money = 0;
return function(){
for ( var i = 0, l = arguments.length; i < l; i++ ){
money += arguments[ i ];
}
return money;
}
})();
var cost = currying( cost ); // 转化成 currying 函数
cost( 100 ); // 未真正求值
cost( 200 ); // 未真正求值
cost( 300 ); // 未真正求值
alert ( cost() ); // 求值并输出:600
curring 函数,首先通过闭包定义了一个私有变量 args,它是用于存储传入的参数的。
当 curring 函数被传入一个回调函数(函数作为参数)时,它会返回一个会执行会用到这个回调函数的函数。
返回的函数里面会保存一个私有变量 arg。
然后有个分支条件,当有参数传入时,会把参数保存到 arg 数组里,并返回原数组;如果没有参数的话,就将 arg 数组作为参数调用回调函数。这里代码是将数组里面的数值进行累加。
你还可以这样使用 cost 函数:
cost(100)(200,300)()
但上面的代码有个缺陷,使用了cost()后,第二次使用cost() 总数将会乘以2,因为money是私有变量,每次计算后,money都会被修改。
解决方法:把 money 不当做私有变量,放到return 里面就可以了。