装饰器是一种特殊类型的声明,它能被附加到类声明,方法,属性或者参数上,可以修改类的行为。

装饰器使用 @expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。

常见的装饰器有:

  • 类装饰器
  • 属性装饰器
  • 方法装饰器
  • 参数装饰器

1 类装饰器

  1. function log(target: any) {
  2. target.prototype.log = function () {
  3. console.log(11111111)
  4. }
  5. return target
  6. }
  7. @log
  8. class User { }
  9. const user = new User()
  10. user.log();

2 属性装饰器

属性装饰器表达式会在运行时当作函数被调用,传入下列两个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
  • 成员的名字
  1. function setDefaultProp(val: string) {
  2. return function (target: any, name: any) {
  3. target[name] = val;
  4. }
  5. }
  6. class Chinese {
  7. // 静态属性,target => 类的构造函数
  8. @setDefaultProp('Chinese people are from china.')
  9. public static region: string = 'china';
  10. // 实例属性,target => 类的原型对象
  11. @setDefaultProp('原型链上的name')
  12. public id!: string;
  13. }
  14. const user = new Chinese()
  15. console.log(user)

image.png

3 方法装饰器

方法装饰器被应用到方法的属性描述符上,可以用来监视、修改、替换方法的定义。

方法装饰器会在运行时传入3个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象;
  • 成员的名字
  • 成员的属性描述符;
  1. // 记录函数耗时
  2. function takeUpTime(target: any, name: string, descriptor: any) {
  3. const func = descriptor.value;
  4. descriptor.value = function () {
  5. const start = new Date().getTime()
  6. func.apply(this, arguments);
  7. const end = new Date().getTime()
  8. console.log(name, '--- 总共耗时', end - start, 'ms')
  9. }
  10. }
  11. class User {
  12. // 静态方法, target => 类的构造函数
  13. @takeUpTime
  14. static run() {
  15. console.log('我在跑步')
  16. for (let i = 0; i < 1000; i++) {
  17. console.log('跑步...')
  18. }
  19. console.log('跑步完了')
  20. }
  21. // 实例方法, target => 类的原型对象
  22. @takeUpTime
  23. study() {
  24. console.log('我在学习')
  25. for (let i = 0; i < 1000; i++) {
  26. console.log('学习...')
  27. }
  28. console.log('学习完了')
  29. }
  30. }
  31. User.run();
  32. const user = new User()
  33. user.study()

4 参数装饰器

参数装饰器表达式会在运行时被调用,可以为类的原型增加一些元素数据,传入3个参数:

  • 对于静态成员来说是类的构造函数,对于实例成员来说是类的原型对象
  • 方法名称
  • 参数在函数参数列表中的索引
  1. function logParams(params: any) {
  2. console.log(params)
  3. return function (target: any, methodName: any, paramIndex: any) {
  4. console.log(target)
  5. console.log(methodName)
  6. console.log(paramIndex)
  7. console.log('---------')
  8. }
  9. }
  10. class User {
  11. // 实例方法, target => 类的原型对象
  12. study(
  13. @logParams('course') course: string,
  14. ) { }
  15. // 静态方法, target => 类的构造函数
  16. static run(
  17. @logParams('where') where: string,
  18. ) { }
  19. }

5 装饰器的执行顺序

当有多个装饰器装饰同一个内容时,

  • 装饰顺序,从里到外
  • 执行顺序,从外到内

不同类型的装饰器:

  • 装饰顺序:属性装饰器 > 方法装饰器 > 参数装饰器 > 类装饰器