每日一句
The only thing stronger than you is you tomorrow.
释义:唯一比你更强大的是明天的你。
前言
编程语言有三种类型:命令式编程、函数式编程、逻辑式编程
在函数式编程中的一些概念:纯函数、高阶函数、柯里化函数
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
指向问题