Skip to content

类装饰器组合

装饰器可以组合使用,执行顺序为:先【由上到下】的执行所有的装饰器工厂,依次获取到装饰器,然后再【由下到上】执行所有的装饰器。

装饰器组合——执行顺序

typescript
//装饰器
function test1(target: Function) {
  console.log("test1");
}
//装饰器工厂
function test2() {
  console.log("test2工厂");
  return function (target: Function) {
    console.log("test2");
  };
}
//装饰器工厂
function test3() {
  console.log("test3工厂");
  return function (target: Function) {
    console.log("test3");
  };
}
//装饰器
function test4(target: Function) {
  console.log("test4");
}

@test1
@test2()
@test3()
@test4
class Person {}

/*
  控制台打印:
    test2工厂
    test3工厂
    test4
    test3
    test2
    test1
*/

装饰器组合——应用

typescript
// 自定义类型Class
type Constructor = new (...args: any[]) => {};

interface Person {
  introduce(): void;
  getTime(): void;
}

// 使用装饰器重写toString方法 + 封闭其原型对象
function customToString(target: Function) {
  // 向被装饰类的原型上添加自定义的 toString 方法
  target.prototype.toString = function () {
    return JSON.stringify(this);
  };
  // 封闭其原型对象,禁止随意操作其原型对象
  Object.seal(target.prototype);
}

// 创建一个装饰器,为类添加日志功能和创建时间
function LogTime<T extends Constructor>(target: T) {
  return class extends target {
    createdTime: Date;
    constructor(...args: any[]) {
      super(...args);
      this.createdTime = new Date(); // 记录对象创建时间
    }
    getTime() {
      return `该对象创建时间为:${this.createdTime}`;
    }
  };
}

// 定义一个装饰器工厂 LogInfo,它接受一个参数 n,返回一个类装饰器
function LogInfo(n: number) {
  // 装饰器函数,target 是被装饰的类
  return function (target: Function) {
    target.prototype.introduce = function () {
      for (let i = 0; i < n; i++) {
        console.log(`我的名字:${this.name},我的年龄:${this.age}`);
      }
    };
  };
}

@customToString
@LogInfo(3)
@LogTime
class Person {
  constructor(public name: string, public age: number) {}
  speak() {
    console.log("你好呀!");
  }
}

const p1 = new Person("张三", 18);
console.log(p1.toString());
p1.introduce();
console.log(p1.getTime());