返回

TypeScript 装饰器及其实践

前端

TypeScript 装饰器的分类

装饰器是一种特殊的函数,它可以在类、方法、属性和参数上使用,用于在不修改源代码的情况下修改类、方法、属性和参数的行为。TypeScript 装饰器主要分为四种类型:

  • 类装饰器:用于修改类的行为。
  • 方法装饰器:用于修改方法的行为。
  • 属性装饰器:用于修改属性的行为。
  • 参数装饰器:用于修改参数的行为。

普通装饰器与装饰器工厂

装饰器可以是普通的装饰器,也可以是装饰器工厂。普通装饰器直接应用于类、方法、属性或参数上,而装饰器工厂则返回一个装饰器。装饰器工厂通常用于创建更复杂的装饰器,例如,可以创建多个装饰器并组合使用。

装饰器的执行顺序

装饰器的执行顺序与它们在代码中出现的顺序相反。也就是说,最先出现的装饰器最后执行,最后出现的装饰器最先执行。

两个装饰器的实例应用

日志装饰器

日志装饰器用于在方法执行前后打印日志。我们可以使用普通装饰器或装饰器工厂来实现日志装饰器。

普通装饰器实现

function log(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
  const originalMethod = descriptor.value;

  descriptor.value = function (...args: any[]) {
    console.log(`Calling ${propertyKey} with args ${args}`);
    const result = originalMethod.apply(this, args);
    console.log(`Called ${propertyKey} with result ${result}`);
    return result;
  };
}

class MyClass {
  @log
  public greet(name: string) {
    return `Hello, ${name}!`;
  }
}

const myClass = new MyClass();
myClass.greet("John");

装饰器工厂实现

function createLogDecorator() {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    const originalMethod = descriptor.value;

    descriptor.value = function (...args: any[]) {
      console.log(`Calling ${propertyKey} with args ${args}`);
      const result = originalMethod.apply(this, args);
      console.log(`Called ${propertyKey} with result ${result}`);
      return result;
    };
  };
}

class MyClass {
  @createLogDecorator()
  public greet(name: string) {
    return `Hello, ${name}!`;
  }
}

const myClass = new MyClass();
myClass.greet("John");

计时装饰器

计时装饰器用于计算方法执行所花费的时间。我们可以使用普通装饰器或装饰器工厂来实现计时装饰器。

普通装饰器实现

function time(target: any, propertyKey: 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(`${propertyKey} took ${end - start} milliseconds to execute`);
    return result;
  };
}

class MyClass {
  @time
  public greet(name: string) {
    return `Hello, ${name}!`;
  }
}

const myClass = new MyClass();
myClass.greet("John");

装饰器工厂实现

function createTimeDecorator() {
  return function (target: any, propertyKey: 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(`${propertyKey} took ${end - start} milliseconds to execute`);
      return result;
    };
  };
}

class MyClass {
  @createTimeDecorator()
  public greet(name: string) {
    return `Hello, ${name}!`;
  }
}

const myClass = new MyClass();
myClass.greet("John");

结语

装饰器是 TypeScript 中一项强大的功能,它可以帮助我们更轻松地编写出更灵活、更易维护的代码。本文介绍了装饰器的分类、普通装饰器与装饰器工厂、装饰器的执行顺序以及两个装饰器的实例应用。希望对大家有所帮助。