函数修饰器(decorator)
js中可以使用高阶函数实现对某个已有函数的功能修饰。比如,有一些计算时间较长的函数,为了优化运行,需要对这些函数添加cache功能,使用函数修饰器模式可以实现有效代码复用。
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
| 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,下面是例子:
1 2 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实现的功能更加方便,下面是其实现:
1 2 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)) } } } }
|
调用这样的柯里化后,可以实现的效果是:
1 2 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)
|