Decorator 装饰器,在 TypeScript 里装饰器就是函数,装饰器可以装饰类,类的属性、方法还有方法的参数等等。装饰器可以处理它装饰的东西,比如给它装饰的东西添加点额外的东西或者修改或替换它装饰的东西。在 Nest.js 应用框架里大量地使用了装饰器。
定义类装饰器
类装饰器就是装饰类用的装饰器,这种装饰器接收一个构造方法参数。
function log(target: any) { console.log('hello ~', target); }
log 其实就是一个函数,只不过根据装饰器要装饰的东西的不同,装饰器函数接收的参数会有一些不同。比如我们这个 log 要装饰类,也就是它是一个类装饰器,那它接收的这个 target 参数就是类的构造方法。log 目前的作用就是在代码运行的时候输出一个 hello,后面加上它接收的 target 参数的值。
使用装饰器
装饰器是个函数,让函数作为装饰器使用,在使用它的时候在函数名字的前面加上一个 @ 符号就可以了。像这样:
@log class Post {}
上面我们用了一个 log 装饰器,装饰了一个叫 Post 的 Class(类)。这样运行代码的时候,就会在控制台上输出:
hello ~ class Post { }
装饰器工厂
如果一个函数的作用是返回一个函数,这个函数可以叫工厂(Factory),因为它的功能就像是工厂一下可以加工生产出来一些东西,函数工厂制造出来的就是函数。装饰器工厂就是可以返回装饰器的函数。
装饰器最终运算出来的是一个可以执行的函数,把装饰器定义成工厂的好处是,我们可以添加自定义的参数,让装饰器更灵活。因为纯装饰器本身要根据它装饰的东西不同使用不同的参数,但装饰器工厂就不一样了,我们可以添加任意的参数,只要工厂最终加工出来的东西是个符合装饰器需求的函数就行,也就是这个函数要包含特定的参数。
function log(name: string = '') { return function(target: any) { console.log('hello ~', name, target); }; }
上面的 log 这次变成了一个装饰器工厂,它会制造(return)出适合装饰类用的装饰器。log 方法接收的参数我们可以随便定义,这样使用这个装饰器的时候,可以设置这些参数的值。比如这里我们添加了一个叫 name 的参数,类型是 string,默认的值是空白。
使用:
@log('ninghao') class Post {}
使用 @log 的时候,给它提供了一个 name 参数的值,执行代码,这次输出的结果是:
hello ~ ninghao class Post { }