认识装饰器
首先装饰器只能用在class上,不能用在func上。包括类、类方法、类属性、类方法的参数、类装饰器。
然后装饰器执行的时机,在定义类的时候执行的。如果对于一个class的func,多个装饰器,那么执行顺序是靠近方法的优先执行。
类装饰器
类装饰器的入参是类的构造函数。有2种常见用法。
用法1:当返回新的构造函数时,可以重载类的构造函数
1 2 3 4 5 6 7 8
   | type ClassConstructorType = { new (...args: any[]): {} };  function userClassDecorator<T extends ClassConstructorType>(constructor: T) {          return class extends constructor {         readonly author: string = "xin-tan.com";         readonly version: string = "1.1.0";     }; }
  | 
 
用法2:可以用于处理原型链,例如不支持新增属性
1 2 3 4
   | function sealed(constructor: Function) {     Object.seal(constructor);     Object.seal(constructor.prototype); }
  | 
 
使用效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | @sealed @userClassDecorator class User {     private readonly name: string;     constructor(name: string) {         this.name = name;     }
      printInfo() {         console.log(JSON.stringify(this));     } }
  const user = new User("dongyuanxin"); user.printInfo(); 
 
   | 
 
类属性装饰器
类属性装饰器入参有2个:
- 第一个参数:对于实例成员是类的原型对象,对于静态成员来说是类的构造函数
 
- 第二个参数:成员名字(属性名字)
 
一个类属性装饰器demo:
1 2 3
   | export function god(target: any, propertyKey: string) {     console.log(">>> target, propertyKey", target, propertyKey); }
  | 
 
使用效果:
1 2 3 4 5 6 7 8 9
   | export class Duty {     @god     private readonly version: string;
      constructor() {         this.version = "1.0.0";     } }
 
  | 
 
类方法装饰器
类方法装饰器入参有3个:
- 第一个参数:对于实例成员是类的原型对象,对于静态成员来说是类的构造函数
 
- 第二个参数:成员的名字(方法装饰器中,就是方法名称)
 
- 第三个参数:成员的属性描述符**(可以用于改造函数的原生行为)**
 
一个记录函数运行时间的类方法装饰器:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
   | export function timeLog(     target: any,     propertyKey: string,     descriptor: PropertyDescriptor ) {     const originalFunc = descriptor.value;     descriptor.value = function (...args: any[]) {         const startTime = Date.now();         const result = originalFunc.call(this, ...args);         console.log(             `>>> ${propertyKey}() cost time is`,             Date.now() - startTime,             "ms"         );         return result;     }; }
   | 
 
使用效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
   | export class Duty {     private readonly version: string;
      constructor() {         this.version = "1.0.0";     }
      @timeLog     run() {         const fs = require("fs");         for (let i = 0; i < 100000; ++i) {             fs.existsSync("package.json");         }     } }
  const duty = new Duty(); duty.run();
 
  | 
 
参考链接
bookmark
bookmark