TS入门——07.装饰器

装饰器概念

ts官方文档上,是这样描述装饰器的,装饰器是一种特殊类型的声明,它能够被附加到类声明,方法, 访问符,属性或参数上,装饰器使用 @expression这种形式,expression求值后必须为一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。
通俗的讲装饰器就是一个方法,可以注入到类、方法、属性参数上来扩展类、属性、方法、参数的功能
装饰器主要有以下几种:

类装饰器

类装饰器是应用于类的装饰器,可以进行类的原型修改和重写属性方法等操作
参数: target:类

// 类装饰器
function boyDecorator(target: any) {
  // 动态扩展类的原型
  target.prototype.name = 'lucky';
  target.prototype.sayHi = function (): void {
    console.log('你好啊!')
  }
}

@boyDecorator
class Boy { }

console.log(Boy.prototype) // { name: 'lucky', sayHi: [Function (anonymous)] }

装饰器工厂

如果我们要定制一个装饰器如何应用到一个声明上,我们得写一个装饰器工厂函数。 装饰器工厂就是一个简单的函数,它本质就是返回一个装饰器,以供装饰器在运行时调用,上面的装饰器写成装饰器工厂

// 类装饰器工厂
function boyDecorator(params: string) {
  return function (target: any) {
    console.log(params) // 再见
    target.prototype.name = 'lucky';
    target.prototype.sayHi = function (): void {
      console.log('你好啊!' + params)
    }
  }
}

@boyDecorator('再见') // 传入相应规则的参数
class Boy { }

console.dir(Boy.prototype) // { name: 'lucky', sayHi: [Function (anonymous)] }

属性装饰器

属性装饰器应用于属性中
参数: target:类,propertyKey:属性名

// 属性装饰器
function attrDecorator(params: string) {
  return function (target: any, name: string) {
    // console.log(params)
    target[name] = params // 给属性赋值'lucky'
  }
}

class Boy {
  @attrDecorator('lucky')
  public name: string | undefined
}

const me = new Boy()
console.log(me.name) // lucky

方法装饰器

属性装饰器应用于方法中,方法装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
target:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
propertyKey:成员的名字
descriptor:成员的属性描述符(可以用来改变方法本身)

// 方法装饰器
function fnDecorator(params: string) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log(descriptor) /* {
      value: [Function (anonymous)], // 对象本身
      writable: true, // 属性值可改性
      enumerable: true, // 可遍历性
      configurable: true // 对象可改性
    } */ 
    console.log(params) // 我被改了
    // 修改方法本身
    descriptor.value = function (): string {
      return params
    }
  }
}

class Boy {
  public name: string = 'lucky'
  @fnDecorator('我被改了')
  getName(): string {
    return this.name
  }
}

const me = new Boy()
console.log(me.getName()) // 我被改了

参数装饰器

参数装饰器声明在一个参数声明之前(紧靠着参数声明)。 参数装饰器应用于类构造函数或方法声明。
参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数
target:对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
propertyKey:方法的名字
parameterIndex:参数在方法参数列表中的索引

// 参数装饰器
function paramsDecorator() {
  return function (target: any, propertyKey: string | undefined, parameterIndex: number) {
    console.log(target) // { getName: [Function (anonymous)] }
    console.log(propertyKey) // getName
    console.log(parameterIndex) // 0
  }
}

class Boy {
  public name: string = 'lucky'
  getName(@paramsDecorator() age: number) {
    return this.name + age
  }
}

const me = new Boy()
console.log(me.getName(12)) // lucky12

访问器装饰符

访问器装饰器声明在一个访问器的声明之前(紧靠着访问器声明)。 访问器装饰器应用于访问器的 属性描述符并且可以用来监视,修改或替换一个访问器的定义
访问器装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
target: 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象
propertyKey: 成员的名字
descriptor:成员的属性描述符

function configDecorator(value: boolean) {
  return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    descriptor.configurable = value; // 改变对象的可配置性
  };
}

class Boy {
  private _name: number;
  private _age: string;
  constructor(name: number, age: string) {
      this._name = name;
      this._age = age;
  }

  @configDecorator(false)
  get name() { return this._name; }

  @configDecorator(false)
  get age() { return this._age; }
}

执行顺序

类中不同声明上的装饰器将按以下规定的顺序应用:

参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个实例成员。
参数装饰器,然后依次是方法装饰器,访问符装饰器,或属性装饰器应用到每个静态成员。
参数装饰器应用到构造函数。
类装饰器应用到类。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值