开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情
参数装饰器
- 参数装饰器声明在一个参数之前(仅靠这参数声明)
- 参数装饰器应用于类构造函数或方法声明
- 装饰器修饰不能声明在文件重载或者其他外部上下文,比如declare类里
- 参数装饰器表达式会在运行时当作函数调用,传入3个参数
- 对于静态成员来说是当前的类,对于实例成员是当前实例
- 参数所在的方法名称
- 参数在参数列表中的索引
target依然是类的原型对象, key是方法名称getInfo index是参数的索引,从0开始
function paramDecorator(target, key, index) {
console.log(target, key, index)
console.log(target===Person.prototype)
}
class Person {
getInfo(@paramDecorator name: string, @paramDecorator age: number) {
console.log(name, age)
}
}
装饰器实例
例子1
这个例子是使用装饰器来包裹类的函数,避免错误语句被抛到全局
const userInfo: any = undefined
function catchDecorator<T extends {}>(target: T, key: string, descriptor: PropertyDescriptor) {
const fn = descriptor.value;
descriptor.value = function () {
try {
fn();
} catch (error) {
console.log('userInfo上不存在' + error)
}
}
}
class Test {
@catchDecorator
getName() {
return userInfo.name
}
@catchDecorator
getAge() {
return userInfo.age;
}
}
const t = new Test();
t.getAge()
t.getName();
例子2
工厂函数创建装饰器,可以在使用时传入一个参数,这样更方便的区别作用在了不同的属性上,如下面的例子,可以清楚的看到错误信息
- 假如getName方法报错,那么错误提示就是userInfo上没有name属性
- 假如getAge方法报错,那么错误提示就是userInfo上没有age属性
const userInfo: any = undefined
function getCatchDecorator(msg: string) {
return function catchDecorator<T extends {}>(target: T, key: string, descriptor: PropertyDescriptor) {
const fn = descriptor.value;
descriptor.value = function () {
try {
fn();
} catch (error) {
console.log('userInfo上不存在' + msg)
}
}
}
}
class Test {
@getCatchDecorator('userInfo上没有name属性')
getName() {
return userInfo.name
}
@getCatchDecorator('userInfo上没有age属性')
getAge() {
return userInfo.age;
}
}
const t = new Test();
t.getAge()
t.getName();
总结:装饰器的使用非常优雅,但是也有一定的学习成本,这种语法增加了代码的复杂度,可读性较差,也可能正式因为种种原因,这个方式还是没有纳入标准。