# Reflect Metadata
Reflect Metadata 属于 ES7 的一个提案,它的主要作用就是在声明的时候「添加和读取元数据」,我们上一节用手动的方法在属性上添加元数据,不仅不优雅而且影响开发效率。
Reflect Metadata 目前需要引入 npm 包才能使用:
npm i reflect-metadata --save
@前端进阶之旅: 代码已经复制到剪贴板
而且需要在 tsconfig.json 中配置 emitDecoratorMetadata.
之后我们就可以用装饰器来获取、添加元数据了.
@Reflect.metadata('name', 'A')
class A {
@Reflect.metadata('hello', 'world')
public hello(): string {
return 'hello world'
}
}
Reflect.getMetadata('name', A) // 'A'
Reflect.getMetadata('hello', new A()) // 'world'
@前端进阶之旅: 代码已经复制到剪贴板
总之:
- Relfect Metadata,可以通过装饰器来给类添加一些自定义的信息
- 然后通过反射将这些信息提取出来
- 也可以通过反射来添加这些信息
反射, ES6+ 加入的 Relfect 就是用于反射操作的,它允许运行中的 程序对自身进行检查,或者说“自审”,并能直接操作程序的内部属性和方法,反射这个概念其实在 Java/c# 等众多语言中已经广泛运用了.
# 基础概念
我们可以先粗略得扫一下 Relfect Metadata 的 API:
// define metadata on an object or property
Reflect.defineMetadata(metadataKey, metadataValue, target);
Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey);
// check for presence of a metadata key on the prototype chain of an object or property
let result = Reflect.hasMetadata(metadataKey, target);
let result = Reflect.hasMetadata(metadataKey, target, propertyKey);
// check for presence of an own metadata key of an object or property
let result = Reflect.hasOwnMetadata(metadataKey, target);
let result = Reflect.hasOwnMetadata(metadataKey, target, propertyKey);
// get metadata value of a metadata key on the prototype chain of an object or property
let result = Reflect.getMetadata(metadataKey, target);
let result = Reflect.getMetadata(metadataKey, target, propertyKey);
// get metadata value of an own metadata key of an object or property
let result = Reflect.getOwnMetadata(metadataKey, target);
let result = Reflect.getOwnMetadata(metadataKey, target, propertyKey);
// get all metadata keys on the prototype chain of an object or property
let result = Reflect.getMetadataKeys(target);
let result = Reflect.getMetadataKeys(target, propertyKey);
// get all own metadata keys of an object or property
let result = Reflect.getOwnMetadataKeys(target);
let result = Reflect.getOwnMetadataKeys(target, propertyKey);
// delete metadata from an object or property
let result = Reflect.deleteMetadata(metadataKey, target);
let result = Reflect.deleteMetadata(metadataKey, target, propertyKey);
// apply metadata via a decorator to a constructor
@Reflect.metadata(metadataKey, metadataValue)
class C {
// apply metadata via a decorator to a method (property)
@Reflect.metadata(metadataKey, metadataValue)
method() {
}
}
@前端进阶之旅: 代码已经复制到剪贴板
看完这些API的命名其实有经验的开发者已经可以猜出来这些API的大概作用了,我们后面会提及,而且这些API接受的参数一共就四种,我们在这里说明一下:
Metadata Key: 元数据的Key,本质上内部实现是一个Map对象,以键值对的形式储存元数据Metadata Value: 元数据的Value,这个容易理解Target: 一个对象,表示元数据被添加在的对象上Property: 对象的属性,元数据不仅仅可以被添加在对象上,也可以作用于属性,这跟装饰器类似
