类的装饰器

作者: 泡杯感冒灵 | 来源:发表于2022-04-15 12:26 被阅读0次
装饰器本身是一个函数,因为装饰器是对类进行修饰的,所以是类的装饰器,装饰器通过@符号来使用。
装饰器接受的参数是一个类的构造函数
function testDecorator (constructor: any) {
      constructor.prototype.getName = () => {
        console.log('weiyang');
      };
}
@testDecorator(true)
class Test{ }
(test as any).getName()
装饰器的运行时机是类创建好后,立即执行,而不是实例化一个类的时候。
可以有多个装饰器,装饰器执行顺序是从下到上,从右到左。
function testDecorator1 (constructor: any) {
      constructor.prototype.getName = () => {
        console.log('yang1');
      };
}
function testDecorator2 (constructor: any) {
      constructor.prototype.getName = () => {
        console.log('yang2');
      };
}

@testDecorator1  @testDecorator2 class Test{ }
对装饰器做工厂模式的包装,就可以做一些参数上的判断了
function testDecorator(flag: boolean) {
  if (flag) {
    return function (constructor: any) {
      constructor.prototype.getName = () => {
        console.log('weiyang');
      };
    }
  } else {
    return function (constructor: any) {}
  }
}


@testDecorator(true)
class Test{ }

const test = new Test();
(test as any).getName()
上边装饰器的写法,我们通过test .getName()的时候,不会主动提示。所以不是一种特别正规的装饰器的写法。正规的怎么写呢?
function testDecorator<T extends new (...args: any[]) => any>(constructor: T) {
  // 这里改造的构造函数后执行
  return class extends constructor{
    name = 'lee';
    getName() {
      return this.name;
    }
  }
}


@testDecorator
class Test{
  name: string;
  // 这个构造函数先执行
  constructor(name: string) {
    this.name = name;
  }
}

const test = new Test('yang');
console.log((test as any).getName());  // 没有改造构造函数之前返回 {name:'yang'},改造之后返回 {name:'lee'}
  • <T extends new (...args:any[]) => any>解析一下这个泛型,泛型T继承了自一个构造函数,这个构造函数,接受任意类型的数据组成的数组作为参数,这个构造函数返回任意类型的数据
  • class extends constructor{}这里是对构造函数进行改写。这个改写的执行是在定义类的构造函数之后执行的。
  • (constructor: T) 这里的意思是 constructor的类型就是一个泛型,这个泛型 T的意思是,可以通过实例化创建出一个类,这个类应该包含new (...args:any[]) => any这样的构造函数
经过上边的写法后,我们去通过test调用getName方法还是会报错,除非是 test as any才可以。原因是 我们定义类test的时候,并没有直接定义getName方法,而getName是testDecorator装饰器偷偷的装饰的时候加进来的,这个时候typescript是不知道加了这个方法的,要解决这个问题,需要工厂模式
function testDecoratorFactory() {
  return function <T extends new (...args: any[]) => any>(constructor: T) {
    // 这里改造的构造函数后执行
    return class extends constructor{
      name = 'lee';
      getName() {
        return this.name;
      }
    }
  }
}


// 这个时候testDecoratorFactory不是当成一个装饰器来用,而是当成一个函数来用
// testDecoratorFactory()函数执行,返回一个装饰器
// 装饰器后边再跟(class {}),表示装饰器装饰的是一个没用名字的class,这个class就多出一个getName的方法了
// 修饰完成之后,把返回的东西复制给 Test
const Test = testDecoratorFactory()(class {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
})

// 这里再去new 的Test是装饰器装饰过后的 class
// 所以实例 test就可以访问到getName了
const test = new Test('yang');
console.log(test.getName());

相关文章

  • 装饰器

    """@装饰器- 普通装饰器- 带参数的装饰器- 通用装饰器- 装饰器装饰类- 内置装饰器- 缓存装饰器- 类实现...

  • 装饰器

    装饰器 decorator类装饰器 带参数的装饰器 举例(装饰器函数;装饰器类;有参与无参) https://fo...

  • 装饰器4

    装饰器装饰类 使用类装饰器的时候,记得要返回被装饰的类调用的结果装饰器函数 再 init 之前执行 例子1:给类添...

  • TS装饰器初体验,用装饰器管理koa接口

    typescript中的装饰器有很多种,比如类装饰器、方法装饰器、属性装饰器等等,先看看装饰器的定义吧,下面以类装...

  • typescript 五种装饰器

    装饰器类型 装饰器的类型有:类装饰器、访问器装饰器、属性装饰器、方法装饰器、参数装饰器,但是没有函数装饰器(fun...

  • decorator

    装饰器 装饰类对象@testclass A{}function test(target){//类对象装饰器函数ta...

  • Python | 装饰器

    使用场景 装饰器 ' @ ' 使用 带参数装饰器 装饰器类

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • 类的装饰器

    装饰器本身是一个函数,因为装饰器是对类进行修饰的,所以是类的装饰器,装饰器通过@符号来使用。 装饰器接受的参数是一...

  • python 装饰器(类装饰器和函数装饰器)

    一、函数装饰器示例 二、类装饰器

网友评论

    本文标题:类的装饰器

    本文链接:https://www.haomeiwen.com/subject/jyjtertx.html