Day20 函数柯里化

65 阅读3分钟

每日一句

The only thing stronger than you is you tomorrow.

释义:唯一比你更强大的是明天的你。

image.png

前言

编程语言有三种类型:命令式编程、函数式编程、逻辑式编程

在函数式编程中的一些概念:纯函数、高阶函数、柯里化函数

1.啥是柯里化函数?
2.为什么要使用柯里化函数
3.柯里化函数的实现原理

柯里化

概念

柯里脂是数学家柯里(Haskell Curry)提出的。

柯里化是指这样一个函数,他接收函数A作为参数,运行后能够返回一个新的函数。并且这个新的函数能够处理函数A的剩余参数。

简单理解:把一个多参函数转变成单参函数的方法。

柯里化实践

有这么个场景:

一个员工的薪酬标准是:基本工资+绩效+年终奖。那么计算一个员工的工资就是:

function salary(name, base, performance, bonus){
  let res = base + performance + bonus;
  console.log(`${name}的工资是: ${res}`)
  return res;
}

salary('小明', 5000, 500, 1000) // 小明的工资是: 6500
salary('小红', 5000, 300, 1500) // 小红的工资是: 6800
salary('李雷', 8000, 300, 1000) // 李雷的工资是: 9300

如果不使用柯里化,每次调用都要传name, base, performance, bonus

如果使用了柯里化

function salary(name, base, performance, bonus){
  let res = base + performance + bonus;
  console.log(`${name}的工资是: ${res}`)
  return res;
}

function curry(fn, ...int) {
  return (...ops) => {
    // 处理参数:合并
    let _args = [...int, ...ops]
    if (_args.length >= fn.length) {
      // 参数刚好达到了fn的参数,执行fn
      return fn.apply(this, _args)
    } else {
      // 递归收集参数
      return curry.call(this, fn, ..._args)
    }
  }
}

// 入职时基本工资是固定的,绩效,年终奖是浮动的
const xm = curry(salary, '小明', 5000)
const xh = curry(salary, '小红', 5000)
const ll = curry(salary, '李雷', 8000)

xm(500)(1000) // 小明的工资是: 6500
xh(300, 1500) // 小红的工资是: 6800
ll(300)(1000) // 李雷的工资是: 9300

// 假设次年年终奖加了一千
xm(500)(2000) // 小明的工资是: 7500
xh(300, 2500) // 小红的工资是: 7800
ll(300)(3000) // 李雷的工资是: 11300

小结

从上述例子可以看出直接调用salary很简单。无非是参数每次都要传,但用了柯里化之后,多加了一个函数就貌似变复杂化了,但在调用的时候变简单了,只需要传入变化的部分,基本不变的就可以安心忽略了,这样传的参数更加的灵活。

实现思路及原理

思路:

  • 返回的是一个函数

  • 收集参数长度与目标函数参数一致就调用目标函数,否则继续返回函数收集参数

  • 调用目标函数传入收集的参数

原理:

利用闭包原理,把参数收集起来,当参数不满足目标函数的长度时,返回一个新函数,继续收集剩余参数,一旦满足才调用目标函数。

应用场景

  • 参数复用

缓存参数到闭包内部参数,然后在函数内部将缓存的参数与传入的参数组合后apply/bind/call给函数执行,来实现参数的复用

  • 提高适用性

使用的不便利性,不同的应用场景往往要传递很多参数,以达到解决特定问题的目的。有时候应用中,同一种规则可能会反复使用,这就可能会造成代码的重复性。

  • 延迟执行

不断的柯里化,累积传入的参数,最后执行。

性能

  • 使用arguments比直接操作命名参数慢

  • 利用闭包对内存会产生额外开销,性能下降

  • 使用apply,call比直接调用函数慢,不使用会导致this指向问题