此装饰器和我理解的java中的「注解」还不是一个意思,java中的注解回顾

这里有完整的装饰器解释

装饰器 不过是在设计时(design time)帮助内省代码,注解**及修改类和属性的函数

装饰器和注解

  • 装饰器(Decorator) 仅提供定义劫持,能够对类及其方法、方法入参、属性的定义并没有提供任何附加元数据的功能。
  • 注解(Annotation) 仅提供附加元数据支持,并不能实现任何操作。需要另外的 Scanner 根据元数据执行相应操作。

注意到装饰器是对类及其方法、入参、属性行为的修改,而注解只是添加元数据,不能修改行为。

  1. @modifyClass
  2. class A {
  3. }
  4. function modifyClass(target: any) {
  5. target.prototype.extraProp = 'decorator'
  6. }

在装饰器的方法中,入参是target,作用于class A上就是 A ,我们知道,在ES中一切都是对象,class 是ES6以后的一个面向对象的语法糖,在这里的A本质也就是一个function,在新建实例的时候作为构造函数调用。这里通过target.prototype我们也能获得这个类的原型。这样我们就可以对这个类进行修改了。

装饰器是在编译期间发生的,这个时候类的实例还没有生成,因此装饰器无法直接对类的实例进行修改。但是可以间接的通过修改类的原型影响实例

这样的修饰器意义不大,我们要应对更多的情况,因此可以给修饰器加上参数,或者叫做「注解」

@modifyClass('param')
class A {

}

function modifyClass(param) {
  return target => {
      target.prototype.extraProp = param
  }
}

之所以要给注解添加引号,是因为注解的概念是要进行元数据的修改,而这里仅仅是动态改变原型上的属性。要进行元数据的修改,我们需要利用反射Reflect。 ES6提供的Refelct并不满足修改元数据,我们要额外引入一个库reflect-metadata

import 'reflect-metadata'

@modifyClass('param')
class A {

}

function modifyClass(param) {
  return target => {
      Reflect.defineMetadata(Symbol.for('META_PARAM'), param, target.prototype)
  }
}

反射给了我们在类及其属性、方法、入参上存储读取数据的能力