TypeScript装饰器

什么是装饰器

装饰器是给一个方法,属性或类扩展一些新的行为,而不是去直接修改它本身的一个函数。
如果在项目中要使用装饰器,需要在 tsconfig.json 的编译配置中开启experimentalDecorators,将它设为 true

使用装饰器

先定义一个函数,这个函数有一个参数,就是要装饰的目标,装饰的作用不同,这个target代表意思也不同。定义了这个函数之后,它就可以作为装饰器,使用@函数名的形式,写在要装饰的内容前面。

function f (taget: any, propertyKey:String) {
  console.log('propertyKey:',propertyKey) //propertyKey: run
}
//定义一个Person类
class Person {
    name: string;
    constructor(name: string) {
       this.name = name;
    }

    @f
    run(): void {//方法
        console.log(this.name+ "在跑步");
    }
}
var p = new Person("张三");
p.run();//张三在跑步

装饰器组合

装饰器可以组合使用,也就是对于同一个目标,使用多个装饰器。

// 可以写在一行
@setName @setAge 
// 可以换行
@setName
@setAge
target

需要注意,多个装饰器的执行顺序:
装饰器工厂从上到下依次执行,但是只是用于返回函数但不调用函数;
装饰器函数从下到上依次执行,也就是执行工厂函数返回的函数。

function setName () {
  console.log('get setName')
  return function (target) {
      console.log('setName')
  }
}
function setAge () {
  console.log('get setAge')
  return function (target) {
      console.log('setAge')
  }
}
//定义一个Person类
@setName() @setAge()
class Person {
    name: string;
    age: number;
    constructor(name: string) {
       this.name = name;
    }
    run(): void {//方法
        console.log(this.name+ "在跑步");
    }
}
var p = new Person("张三");
p.run();//张三在跑步
// get setName
// get setAge
// setAge
// setName
// 张三在跑步

类装饰器

类装饰器在类声明之前声明,它有唯一的参数target,就是装饰的这个类。
通过装饰器,就可以修改类的原型对象和构造函数


function setName (name: string) {
 return function (target: Function) {
     console.log('setName')
 }
}
function addName(constructor: Function) {
   constructor.prototype.name = "小浩";
}
@setName('里斯')
@addName
class Person {
   name: string;
   age: number;
   constructor() {}
}
const person = new Person();
console.log(person.name); //小浩

方法装饰器

方法装饰器用来处理类中方法,它可以处理方法的属性描述符,可以处理方法定义。方法装饰器在运行时也是被当做函数调用,含 3 个参数:
装饰静态成员时是类的构造函数,装饰实例成员时是类的原型对象
装饰方法的名字
装饰方法的属性描述符

function logmethod (bool: boolean):any { 
 return function (target: any, propertyName: string, descriptor: PropertyDescriptor) { 
  console.log(propertyName) // run
  console.log(descriptor) // {writable: true, enumerable: false, configurable: true, value: ƒ}

  //修改属性描述
  // descriptor.enumerable = bool;
  return {
   value: function() {
     return 28;
   },
   enumerable: bool
 };
 }
}
class Person {
   name: string;
   age: number;
   constructor() {
      
   }

   @logmethod(false)
   getAge ():any {//方法
    return this.age;
   }
}
const p = new Person();
console.log(p.getAge()); 

属性装饰器

属性装饰器声明在属性声明之前,它有 2 个参数,和方法装饰器的前两个参数是一样的。
属性装饰器没法操作属性的属性描述符,它只能用来判断某各类中是否声明了某个名字的属性。

function printPropertyName(target: any, propertyName: string) {
  console.log(propertyName);
}
class Info {
  @printPropertyName // name
  name: string;
  @printPropertyName // age
  age: number;
}

参数装饰器

参数装饰器,顾名思义是用于修饰参数的装饰器。

function logName (target: Object, propertyKey: string, index: number) { 
 console.log(target) //{constructor: ƒ, work: ƒ}
 console.log(propertyKey) //work
 console.log('logName',index) // 0
}

function logdoname (target: Object, propertyKey: string, index: number) { 
 console.log(target) //{constructor: ƒ, work: ƒ}
 console.log(propertyKey) //work
 console.log('logdoname',index) // 1
}

class Person {
 name: string;
 age: number;
 constructor() {
    
 }

 work (@logName name:string,@logdoname doname:string):any {//方法
  console.log(name + '在' + doname)
 }
}
const p = new Person();
p.work('小浩','工作') 

参数装饰器有三个参数 target、propertyKey、index
target:当前对象的原型
propertyKey:参数的名称
index:参数数组中的位置,比如上例中参数 name 的位置是 0, doname 的位置为 1


  转载请注明: 小浩之随笔 TypeScript装饰器

 上一篇
ES6-手写Promise ES6-手写Promise
首先Promise有三个状态 PENDING、FULFILLED、REJECTED ,只能由PENDING改变为FULFILLED、REJECTED,并且只能改变一次 Promise接收一个函数,这个函数有两个参数resolve方法和rej
2022-03-04
下一篇 
TypeScript泛型 TypeScript泛型
在编程中,定义一个变量不确定类型的时候有两种解决方式: 1.使用any 2.使用泛型 什么是泛型 泛型是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候在指定类型的一直特征。 为什么要使用泛型 因为any会在调试中丢失很多
2021-10-25
  目录