js函数柯里化(function currying)

Posted A_山水子农

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了js函数柯里化(function currying)相关的知识,希望对你有一定的参考价值。

  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)
// 3
addTen(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 = 0
let 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 = 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

  柯里化是高阶函数应用中的一种,此处稍微介绍一下高阶函数,高阶函数是指至少满足下列条件之一的函数:

  • 函数可以作为参数被传递
  • 函数可以作为返回值输出

以上是关于js函数柯里化(function currying)的主要内容,如果未能解决你的问题,请参考以下文章

js函数柯里化的理解

js - 函数的柯里化(Currying)

js - 函数的柯里化(Currying)

JS中的柯里化(currying)

JavaScript函数的柯里化(currying)

js的柯里化currying