??currying又称部分求值。一个currying的函数首先会接受一些参数,接受了这些参数之后,该函数不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正求值的时候,之前传入的所有参数都会被一次性用于求值。
??currying简单的说就是:只传递给函数一部分参数来调用它,让它返回一个函数去处理剩下的参数。你可以一次性地调用 curry 函数,也可以每次只传一个参数分多次调用。
??下面先用一个简单的例子实现函数柯里化:
let add = function(x, y){ return x + y}
??把add函数柯里化成这样:
var addCurrying = function(x) { return function(y) { return x + y }}var increment = addCurrying(1)var addTen = addCurrying(10)increment(2)// 3addTen(2)// 12
?? addCurrying 函数接受一个参数并返回一个新的函数。调用 addCurrying 之后,返回的函数就通过闭包的方式记住了 addCurrying 的第一个参数x。currying函数可以复用一些传入的参数,形成闭包保存在函数内,调用时只需要传入变化的数据。
/** * @description 柯里化函数 * @param {Function} fn 传入的需要运算的函数 * @return {Function} 返回函数 */ let curry = function (fn) { // args保存需要复用的参数 let reuseArgs = Array.prototype.slice.call(arguments, 1) return function () { // selfArgs是自身参数 let selfArgs = Array.prototype.slice.call(arguments) // 合并自身参数和复用的参数 let mergeArgs = reuseArgs.concat(selfArgs) // 计算返回结果 return fn.apply(null, mergeArgs) } } /** * @description 求和 * @return {Number} 求和的值 */ let add = function () { let args = Array.prototype.slice.call(arguments) let sum = 0 for (let i = 0; i < args.length; i++) { sum += args[i] } return sum } // 3, 4, 5是固定不变,可复用的参数 let curryAdd = curry(add, 3, 4, 5) curryAdd(6) // 结果为18 curryAdd(7, 8) // 结果为27
??假设我们要编写一个计算每月的开销函数。每天结束之前,我们都要记录今天花掉了多少钱。
let monthlyCost = 0let cost = function (money) { monthlyCost += money}cost(100) // 第1天的开销cost(200) // 第2天的开销cost(300) // 第3天的开销cost(500) // 第30天的开销console.log(monthlyCost) // 1100
??我们其实并不太关心每天花掉了多少钱,只是想知道到了月底的时候总共花掉了多少钱;所以每个月的前29天,我们都只要保存好当天的开销就行了,不要进行计算,到了第30天才进行求值计算,得到当月的开销。currying函数在参数复用的同时可以实现延迟计算。
/** – @description 计算当月的开销 – @return {Number} 返回计算值 */ let cost = function () { let money = 0 for (let i = 0; i < arguments.length; i++) { money += arguments[i] } return money } /** – @description 柯里化函数 – @param {Function} fn 传入的需要运算的函数 – @return {Function} 返回函数 */ let currying 便宜美国vps = function (fn) { // args保存需要复用的参数 let reuseArgs = Array.prototype.slice.call(arguments, 1) // 定义一个保存复用参数和自身参数的数组 let args = reuseArgs return function () { // arguments是自身参数 if (arguments.length === 0) { return fn.apply(null, args) } else { [].push.apply(args, arguments) } } } let costCurrying = currying(cost) costCurrying(100) // args为[100] 未真正求值 costCurrying(200) // args为[100, 200] 未真正求值 costCurrying(300) // args为[100, 200, 300] 未真正求值 costCurrying(500) // args为[100, 200, 300, 500] 未真正求值 console.log(costCurrying()) // 求值并输出结果:1100
??柯里化是高阶函数应用中的一种,此处稍微介绍一下高阶函数,高阶函数是指至少满足下列条件之一的函数:
函数可以作为参数被传递函数可以作为返回值输出 84160760