参数装饰器和小例子

46 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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();

image.png 总结:装饰器的使用非常优雅,但是也有一定的学习成本,这种语法增加了代码的复杂度,可读性较差,也可能正式因为种种原因,这个方式还是没有纳入标准。