JavaScript专题之函数柯里化
JS 函数式编程指南html
不少人对于柯里化的理解仅仅停留在“复用参数”上。但我认为函数式编程思想更重要做用的是:解除函数对执行时参数的依赖,加强函数的泛化能力,让函数仅仅包含“纯粹的操做逻辑”,这些操做逻辑要用在什么样的输入上,使用函数时再决定。git
使用柯里化的场景:github
function getProp(obj, key)
)function getProp(obj, key) { return obj[key]; }
)获得的函数就仅仅封装了“操做逻辑”,函数对于操做的输入不作任何假设,所以函数的泛化能力很强,能够处理任何合法的输入。(在这个例子中,getProp
能够从任何对象中获取任何属性)编程
“不作任何假设”的说法其实不太准确,好比说getProp
就假设了obj
参数必须是对象,但这种假设是“完成操做逻辑”的必要要求,“不作任何多余的假设”更准确一些。我在这里使用更绝对的语气,是为了加强本身对这个观点的印象。
getProp(obj1, 'key1')
和getProp(obj2, 'key2')
,函数能适应任何合法的输入,无论调用多少次,无论传入什么参数,函数的操做逻辑都不会改变)let getPropFromArrProto = curry(getProp, Array.prototype);
经过这个新的函数就能直接从Array.prototype
中获取属性)function curry(fn, ...priorArgs) { const length = fn.length; return function judge(...restArgs) { return priorArgs.length + restArgs.length >= length ? fn.call(this, ...priorArgs, ...restArgs) : function (...args) { return judge.call(this, ...restArgs, ...args); } } } // 测试代码 var fn = curry(function (a, b, c, d) { console.log([a, b, c, d]); return [a, b, c, d]; }, 'p'); fn("a", "b", "c") // [ 'p', 'a', 'b', 'c' ] fn("a", "b")("c") // [ 'p', 'a', 'b', 'c' ] fn("a")("b")("c") // [ 'p', 'a', 'b', 'c' ] fn("a")("b", "c") // [ 'p', 'a', 'b', 'c' ]
其中,ide
priorArgs.length + restArgs.length >= length ? fn.call(this, ...priorArgs, ...restArgs) : function (...args) { return judge.call(this, ...restArgs, ...args); }
它的意思是,若是已经接受的参数数量很多于fn
(被柯里化的函数)期待的参数数量,就调用fn并返回结果。
不然,返回一个新的函数,这个函数期待剩余的参数。
调用这个新函数会再次进行参数数量的判断,若是已经接受的参数数量很多于fn
(被柯里化的函数)期待的参数数量,就调用fn并返回结果,不然返回一个新的函数……以此类推。函数式编程