logo
Laucher

Laucher

Laucher

2022年 10月 23日

0

TypeScript的装饰器

TypeScript 装饰器是一种特殊类型的声明,它可以附加到类、方法、属性或参数上,用于修改类的行为或添加额外的元数据。装饰器是一种在编译时进行元编程的技术,它使得我们可以以声明性的方式对类和类成员进行扩展或修改,而无需修改原始类的代码。

封面图

装饰器的定义和使用方法

装饰器是一种特殊类型的声明,通过 @ 符号后跟一个装饰器工厂函数来表示。装饰器工厂函数接收不同的参数,并返回一个装饰器函数。装饰器函数可以在类定义时被调用,用于修改类的行为或添加额外的元数据。

类装饰器

类装饰器用于修饰类的构造函数。它接收一个参数,即目标类的构造函数。

function classDecorator(constructor: Function) {
  console.log("Class Decorator");
}

@classDecorator
class MyClass {
  // 类的定义
}

在上述例子中,classDecorator 是一个类装饰器,它在 MyClass 类定义时被调用,输出 “Class Decorator”。

方法装饰器

方法装饰器用于修饰类的方法。它接收三个参数:目标类的原型对象,方法的名称和方法的属性描述符。

function methodDecorator(target: any, methodName: string, descriptor: PropertyDescriptor) {
  console.log("Method Decorator");
}

class MyClass {
  @methodDecorator
  myMethod() {
    // 方法的定义
  }
}

在上述例子中,methodDecorator 是一个方法装饰器,它在 myMethod 方法定义时被调用,输出 “Method Decorator”。

属性装饰器

属性装饰器用于修饰类的属性。它接收两个参数:目标类的原型对象和属性的名称。

function propertyDecorator(target: any, propertyName: string) {
  console.log("Property Decorator");
}

class MyClass {
  @propertyDecorator
  myProperty: number;
}

在上述例子中,propertyDecorator 是一个属性装饰器,它在 myProperty 属性定义时被调用,输出 “Property Decorator”。

参数装饰器

参数装饰器用于修饰类的方法参数。它接收三个参数:目标类的原型对象、方法的名称和参数的索引。

function parameterDecorator(target: any, methodName: string, parameterIndex: number) {
  console.log("Parameter Decorator");
}

class MyClass {
  myMethod(@parameterDecorator param: string) {
    // 方法的定义
  }
}

在上述例子中,parameterDecorator 是一个参数装饰器,它在 myMethod 方法的参数 param 定义时被调用,输出 “Parameter Decorator”。

装饰器的应用场景

装饰器在 TypeScript 中有许多应用场景,它可以用于:

  1. 日志记录:通过方法装饰器来记录方法的调用和参数,实现日志记录功能。
function log(target: any, methodName: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    console.log(`用参数 ${args.join(", ")}调用${methodName}`);
    return originalMethod.apply(this, args);
  };
}

class MyClass {
  @log
  myMethod(name: string) {
    console.log(`Hello, ${name}!`);
  }
}

const instance = new MyClass();
instance.myMethod("Laucher");
// 输出:
// 用参数Laucher调用myMethod
// Hello, Laucher!
  1. 权限控制:通过方法装饰器来检查用户权限,实现权限控制功能。
function checkPermission(target: any, methodName: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    if (userHasPermission()) {
      return originalMethod.apply(this, args);
    } else {
      console.log("Permission denied.");
    }
  };
}

class MyClass {
  @checkPermission
  sensitiveOperation() {
    // 敏感操作的实现
  }
}
  1. 数据校验:通过属性装饰器来检查属性的合法性,实现数据校验功能。
function validate(target: any, propertyName: string) {
  let value = target[propertyName];

  const getter = function () {
    return value;
  };

  const setter = function (newValue: number) {
    if (newValue < 0) {
      throw new Error("Value必须 >= 0");
    }
    value = newValue;
  };

  Object.defineProperty(target, propertyName, {
    get: getter,
    set: setter,
  });
}

class MyClass {
  @validate
  price: number;
}

const instance = new MyClass();
instance.price = 100; // 有效
instance.price = -50; // 抛出错误:VValue必须 >= 0
  1. 路由映射:通过类装饰器和方法装饰器来映射路由,实现路由控制功能。
function route(path: string) {
  return function (target: Function) {
    // 实现路由映射逻辑
  };
}

function get(target: any, methodName: string, descriptor: PropertyDescriptor) {
  // 实现路由映射逻辑
}

@route("/users")
class UserController {
  @get
  getUsers() {
    // 获取用户列表的实现
  }
}
  1. 依赖注入:通过类装饰器和参数装饰器来实现依赖注入,简化类的构造函数注入依赖的过程。
const ServiceToken = Symbol("ServiceToken");

function injectService(target: any, propertyName: string, parameterIndex: number) {
  const service = getServiceInstance();
  target[propertyName] = service;
}

class MyClass {
  constructor(@injectService private service: Service) {
    // 类的构造函数
  }

  doSomething() {
    this.service.doSomething();
  }
}
  1. 性能监测:通过方法装饰器来监测方法的执行时间,实现性能监测功能。
function performanceMonitor(target: any, methodName: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;
  descriptor.value = function (...args: any[]) {
    const start = performance.now();
    const result = originalMethod.apply(this, args);
    const end = performance.now();
    console.log(`方法 ${methodName}的执行时间为${end - start}毫秒。`);
    return result;
  };
}

class MyClass {
  @performanceMonitor
  heavyOperation() {
    // 重型操作的实现
    // 例如:排序大数组、复杂计算等
  }
}

const instance = new MyClass();
instance.heavyOperation();
// 输出:方法heavyOperation的执行时间为123.45毫秒。

评论