JS 浅谈函数柯里化,不明觉厉
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术。这个技术由 Christopher Strachey 以逻辑学家 Haskell Curry 命名的,尽管它是 Moses Schnfinkel 和 Gottlob Frege 发明的。
柯里化函数思想
函数柯里化(function currying)又称部分求值。一个currying的函数首先会接受一些参数,接受了这些参数后,该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包里被保存起来。待到函数真正需要求值的时候,之前传入的参数都会被一次性用于求值。
假设我们要编写一个计算每月开销的函数。在每天结束之前,我们都要记录今天花了多少钱,代码如下:
let result = 0; let add = function(num){ result += num; console.log(result); } add(10); // 10 add(5); // 15 add(8); // 23
这段代码在每天结束后都会记录并计算到今天为止花了多少钱,但我们不太关心每天花掉多少,只想知道月底总共花掉了多少,也就是说,只需要在月底计算一次。
如果在每个月的前二十九天,我们都只是保存好当天的开销,直到第30天才进行求值计算,这就达到了我们的目的。
柯里化实现
- 当函数调用有参数时,保存参数,作为下次调用的参数
- 当函数调用无参数时,计算结果
最终,我们要实现这样的方案,curry函数可以多次调用,每次调用的参数不定;当函数调用无参数时,输出最终结果
// curry - 柯里化函数 // fn - 计算结果的函数 // args - 参数 curry(fn, args...)(args...)(args...)();
废话不多说,直接上代码:
let add = function(){ let args = Array.prototype.slice.call(arguments); let result = 0; args.forEach((item, key)=>{ result += item; }) console.log(result); return result; } let curry = function(fn){ let args = Array.prototype.slice.call(arguments, 1); return function(){ let args_add = Array.prototype.slice.call(arguments); let newArgs = args.concat(args_add); if(args_add.length){ // 当函数调用无参数时,计算结果 return curry.call(null, fn, ...newArgs); }else{ // 当函数调用有参数时,保存参数,作为下次调用的参数 return fn.apply(null, newArgs); } } } curry(add, 1, 2)(4, 5)(); // 12
柯里化意义
1、延迟计算。(就像烹饪一样,食材全部准备好后,厨师才开始做菜)
2、参数复用。当在多次调用同一个函数,并且传递的参数绝大多数是相同的,那么该函数可能是一个很好的柯里化候选。
3、动态创建函数。这可以是在部分计算出结果后,在此基础上动态生成新的函数处理后面的业务,这样省略了重复计算。或者可以通过将要传入调用函数的参数子集,部分应用到函数中,从而动态创造出一个新函数,这个新函数保存了重复传入的参数(以后不必每次都传)
欢迎大家指正喽,哈哈