参考链接
函数柯里化
含义
柯里化:是固定部分参数,返回一个接受剩余参数的函数,也称为部分计算函数,目的是为了缩小适用范围,创建一个针对性更强的函数,核心思想是把多参数传入的函数拆成单(部分)参数函数,内部再返回下一个单(部分)参数函数,依次处理剩余函数
反柯里化:扩大适用范围,创建一个应用范围更广的函数,使本来只有特定对象才适用的方法,扩展到更多对象
通用实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| Function.prototype.unCurrying = function() { const self = this return function(...rest) { return Function.prototype.call.apply(self, rest) } } const push = Array.prototype.push.unCurrying()
Function.prototype.unCurrying = function() { return this.call.bind(this) }
function unCurrying(fn) { return function(tar, ...argu) { return fn.apply(tar, argu) } }
|
使用反柯里化
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| Function.prototype.unCurrying = function() { const self = this return function(...rest) { console.log(rest, 'uncurrying rest') return Function.prototype.call.apply(self, rest) } } const push = Array.prototype.push.unCurrying() ~function(...rest) { console.log(rest, 'before') push(rest, 4, 5) console.log(rest, 'after') }(1,2,3)
|
反柯里化其实反映的是一种思想 - 扩大方法的适用范围
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| Function.prototype.unCurrying = function() { const self = this return function(...rest) { console.log(rest, 'uncurrying rest') return Function.prototype.call.apply(self, rest) } } const push = Array.prototype.push.unCurrying() ~function() { let rest = {a: 3} console.log(rest, 'before') push(rest, 4, 5) console.log(rest, 'after') }(1,2,3)
|
只要是方法就可以借用 unCurrying 方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| var call = Function.prototype.call.unCurrying() function $(id) { return this.getElementById(id) } call($, document, 'demon')
const unCurrying = Function.prototype.unCurrying.unCurrying() const map = unCurrying(Array.prototype.map) map({0: 4, 1: 'a', 2: null, length: 3}, n => n + n)
~~~~
#### 总结
函数柯里化 ~~~js function(arg1, arg2) function(arg1, arg2, arg3) function(arg1, arg2, arg3, arg4)
|
反柯里化
终点知识解析
Function.prototype.call.apply(self, rest)
小例子:
1
| Math.Max.apply([], [1, 2, 3])
|
先执行 apply 将 math 替换成 []
然后在执行 Max 并传入[1,2,3],此时因为 apply 的关系 [1,2,3]扁平化为1,2,3
Function.prototype.call.apply(self, rest)
过程
Function.prototype.call.apply(Array.prototype.push, rest)
Array.prototype.push.call(...rest)
所以在传递 rest 的时候,需要操作的对象放在第一位,方便 call 绑定 this
- rest[0].push(rest.shift(1))
1 2 3 4 5 6
| var obj = {a: 3} Array.prototype.push.call(obj, 4, 5) obj var obj = {a: 3, b: 3} Array.prototype.push.call(obj, 4, 5) obj
|