每日一句
Age wrinkles the body, Quitting wrinkles the soul.
释义:岁月使皮肤起皱,放弃使灵魂起皱。
函数反柯里化
简介
函数柯里化:是一个多参的函数,我们可以先固定部分参数,返回一个可以接收剩余参数的函数,无形之间缩小了函数的适用范围。
函数反柯里化:字面上理解,功能跟柯里化相反,扩大适用范围,创建一个应用范围更广的函数。
反柯里化Uncurrying
的话题来自JavaScript之父 Brendan Eich在2011年发表的一篇推特,它解决的问题是让对象去借用一个原本不属于自己的方法。
代码理解方式:对象.某函数(参数1, 参数2)
转成某函数(对象, 参数1, 参数2)
代码实现方式
通用方式
在Function
的原型上添加uncrurring
方法,在执行时把uncrurring
方法保存到self
上;
借用apply
把要借用的函数作为this
环境赋给call
,并传入之后的参数执行。
Function.prototype.uncrurring = function() {
const self = this
return (...args) => {
return Function.prototype.call.apply(self, ...args)
}
}
bind方式
Function.prototype.uncrurring = function(fn) {
return fn.call.bind(this)
}
自定义函数
function uncrurring(fn) {
return (obj, ...args) => {
return fn.apply(obj, args)
}
}
使用场景
- 示例1: 简单文字替换
Function.prototype.unCurrying = function() {
const self = this
return function(...args) {
return Function.prototype.call.apply(self, args)
}
}
const call = replaceTxt.unCurrying()
const Man = {
ability: ['唱歌', '跳舞']
}
function replaceTxt(...args) {
args.forEach(item => {
if (this.ability.includes(item)) {
console.log(`🤣:我会${item}.`)
console.log(`🦜:我会${item}.`)
} else {
console.log(`🤣:我会${item}.`)
console.log('🦜:你放P!')
}
})
}
~function(...args) {
call(Man, ...args)
}('唱歌', '跳舞', '飞!')
// 输出结果:
🤣:我会唱歌.
🦜:我会唱歌.
🤣:我会跳舞.
🦜:我会跳舞.
🤣:我会飞!.
🦜:你放P!
- 示例2:对象也能用push
let Person = {
name: 'zhangsan'
}
const pushObj = Array.prototype.push.unCurrying()
pushObj(Person, {age: 30}, {eat: () => console.log('我吃鱼!')})
console.log(Person)
/* {
'0': { age: 30 },
'1': { eat: [Function: eat] },
name: 'zhangsan',
length: 2
} */
- 示例3: 自己也可以借用
本身也是一个方法
const unCurrying = Function.prototype.unCurrying.unCurrying()
const Map = unCurrying(Array.prototype.map)
const Obj = { 0: '王小二', 1: '张小明', 2: '捣蛋鬼', length: 3 }
console.log(Map(Obj, n => n + '真棒!'))
// [ '王小二真棒!', '张小明真棒!', '捣蛋鬼真棒!' ]