函数修饰器(decorator)
js中可以使用高阶函数实现对某个已有函数的功能修饰。比如,有一些计算时间较长的函数,为了优化运行,需要对这些函数添加cache功能,使用函数修饰器模式可以实现有效代码复用。
| 12
 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
 
 | let worker = {
 slow(min,max) {
 return min+max
 }
 }
 
 function cachingDecorator(func, hash) {
 let cache = new Map()
 return function() {
 let key = hash(arguments)
 if(cache.has(key)) {
 return cache.get(key)
 }
 let result = func.apply(this,arguments)
 cache.set(key,result)
 return result
 }
 }
 
 function hash(args){
 return args[0]+','+args[1]
 }
 
 worker.slow = cachingDecorator(worker.slow,hash)
 
 console.log(slow(3,5))
 console.log(slow(3,5))
 
 | 
在上面的例子中,使用hash函数对函数参数列表arguments进行哈希,得到key,然后再用Map进行缓存。使用func.apply来让修饰后的函数不丢失this信息。
偏函数(partials)
使用bind可以实现偏函数功能,可以按照顺序从左往右绑定this以及任意个数的参数,bind的语法是这样的:
| 1
 | let bound = func.bind(context,arg1,arg2,...)
 | 
如果想不按照参数顺序,实现任意函数参数的绑定,可以使用js中的_.partial,下面是例子:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | function greet(greeting, name) {return greeting + ' ' + name
 }
 
 let sayHelloTo = _.partial(greet, 'hello')
 sayHelloTo('Tom')
 
 
 
 let greetTom = _.partial(greet,_,'Tom')
 greetTom('Tom')
 
 
 | 
柯里化(currying)
柯里化的定义是,把函数f(a,b,c,d)转化成f(a)(b)(c)(d),以此实现对部分函数参数的预加载。
js中的_.curry实现的功能更加方便,下面是其实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | function curry(func){return function curried(...args) {
 if(args.length >= func.length){
 return func.apply(this,args)
 }else{
 return function(...args2) {
 return curried.apply(this,args.concat(args2))
 }
 }
 }
 }
 
 | 
调用这样的柯里化后,可以实现的效果是:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | function sum(a,b,c){return a+b+c
 }
 
 let curriedSum = _.curry(sum)
 
 curriedSum(1,2,3)
 curriedSum(1,2)(3)
 curriedSum(1)(2,3)
 curriedSum(1)(2)(3)
 
 |