Appearance
reflect-metadata
是一个用于 TypeScript 和 ECMAScript 提案的元数据反射库。它通过提供对元数据的定义和检索支持,简化了装饰器(Decorators)的使用。该库实现了多种元数据相关功能,可以在类、方法、参数和属性上设置和获取元数据。
Metadata(元数据),简单的说,就是为真正的数据提供额外的信息。例如,如果一个变量表示一个数组,那么数组的length就是其元数据。相似的,数组中的每个元素是数据的话,那么数据类型就是其元数据。更加宽泛的讲,元数据不仅仅是编程中的概念,它能够帮助我们更快的实现一些事情。举几个例子
如果你有一个变量 name,它的值可能是一个字符串 "Alice"。但元数据可以告诉你更多,比如这个字符串的长度、它的类型是字符串、这个数据的来源(例如从哪个数据库表中获取的)、是否是必填字段等。
在图像文件中,元数据可能包括文件的分辨率、拍摄时间、拍摄地点以及相机型号等。
使用
要使用 reflect-metadata
,首先需要将其安装到你的项目中。
bash
npm install reflect-metadata
1
在使用 reflect-metadata
之前,需要在代码的入口文件(例如 index.ts 或 main.ts)中引入 reflect-metadata
:
api 说明
reflect-metadata
是一个用于在对象上定义和管理元数据的 TypeScript 库。它通过提供一组标准化的 API,使开发者能够在对象、类和方法上附加和读取元数据。这些 API 包括定义、获取、检查和删除元数据等操作。
API 名称 | 描述 | 参数 | 使用示例 |
---|---|---|---|
Reflect.defineMetadata | 在目标对象上定义元数据(键值对)。 | metadataKey , metadataValue , target , propertyKey (propertyKey 可选) | Reflect.defineMetadata('key', 'value', targetObject, 'propertyName'); |
Reflect.getMetadata | 获取目标对象上定义的元数据。 | metadataKey , target , propertyKey (propertyKey 可选) | const value = Reflect.getMetadata('key', targetObject, 'propertyName'); |
Reflect.getOwnMetadata | 获取目标对象自身(不包括原型链)上定义的元数据。 | metadataKey , target , propertyKey (propertyKey 可选) | const value = Reflect.getOwnMetadata('key', targetObject, 'propertyName'); |
Reflect.hasMetadata | 检查目标对象上是否存在指定键的元数据。 | metadataKey , target , propertyKey (propertyKey 可选) | const hasKey = Reflect.hasMetadata('key', targetObject, 'propertyName'); |
Reflect.hasOwnMetadata | 检查目标对象自身(不包括原型链)上是否存在指定键的元数据。 | metadataKey , target , propertyKey (propertyKey 可选) | const hasKey = Reflect.hasOwnMetadata('key', targetObject, 'propertyName'); |
Reflect.deleteMetadata | 删除目标对象上指定键的元数据。 | metadataKey , target , propertyKey (propertyKey 可选) | const result = Reflect.deleteMetadata('key', targetObject, 'propertyName'); |
Reflect.getMetadataKeys | 获取目标对象上所有元数据键,包括原型链中的键。 | target , propertyKey (propertyKey 可选) | const keys = Reflect.getMetadataKeys(targetObject, 'propertyName'); |
Reflect.getOwnMetadataKeys | 获取目标对象自身(不包括原型链)上所有元数据键。 | target , propertyKey (propertyKey 可选) | const keys = Reflect.getOwnMetadataKeys(targetObject, 'propertyName'); |
Reflect.metadata | 一个工厂函数,用于创建装饰器,将元数据附加到目标对象上。用于类或类成员的装饰器。 | metadataKey , metadataValue | @Reflect.metadata('key', 'value') |
参数解释
- metadataKey: 表示元数据的键。类型可以是任意的,通常使用字符串或符号。
- metadataValue: 表示元数据的值。类型可以是任意的。
- target: 元数据附加到的目标对象。通常是类的原型或者类的构造函数。
- propertyKey (可选): 元数据附加到的属性或方法的名称。类型为字符串或符号。
每个 API 的参数组合形成了一个唯一的元数据定义或查询:
target + metadataKey
: 元数据附加到类或对象上。target + propertyKey + metadataKey
: 元数据附加到对象或类的特定属性或方法上。
案例
案例中 value 也可是对象不用像案例中只是基本属性
js
import "reflect-metadata";
class Person {
myProperty: string;
say() {
return 123;
}
}
const p = new Person();
// ------------ 类似set defineMetadata---------------------
// 定义键值对存储 target + metadataKey : value
Reflect.defineMetadata("metadataKey", "123", p);
// 定义键值对存储 target + propertyKey + metadataKey:value
// myProperty1 任意字段值 不一定非要是 对象自己的
Reflect.defineMetadata("metadataKey", "456", p, "myProperty");
// 原型链上保存 一般原型链上的都是共享属性 也就是function a.__proto__ ==> A.property (A.property.constructor A.propKey.xxxxFun)
Reflect.defineMetadata("metadataKey1", "789", Person.prototype);
// ------------类似get getMetadata ------------------获取原型链上的值
const metadataValue = Reflect.getMetadata("metadataKey", p);
// 必须 target + propertyKey + metadataKey key 才能获取value
const metadataValue1 = Reflect.getMetadata("metadataKey", p, "myProperty");
// 也会获取原型链上的值
console.log(Reflect.getMetadata("metadataKey1", p)); // 789
console.log(metadataValue); // 123
console.log(metadataValue1); // 456
console.log(p);
//---------------- getOwnMetadata --------------只有自身的
console.log(Reflect.getOwnMetadata("metadataKey1", p)); // undefined 原型链上的不会获取
// ------------- Reflect.getMetadataKeys 原型链上 key 也会打印 ---------------------------注意第二参数是 `propertyKey`
console.log(Reflect.getMetadataKeys(p)); // [ 'metadataKey', 'metadataKey1' ]
console.log(Reflect.getMetadataKeys(p, "myProperty")); // [ 'metadataKey' ]
// ------------- Reflect.getOwnMetadataKeys 只会打印自身的不包含原型链 ---------------------------注意第二参数是 `propertyKey`
console.log(Reflect.getOwnMetadataKeys(p)); // [ 'metadataKey' ]
console.log(Reflect.getOwnMetadataKeys(p, "myProperty")); // [ 'metadataKey' ]
// ----------------Reflect.hasMetadata ----------- 包含原型链
console.log(Reflect.hasMetadata("metadataKey", p)); // true
console.log(Reflect.hasMetadata("metadataKey1", p)); // true
// ----------------Reflect.hasOwnMetadata ----------- 不包含原型链
console.log(Reflect.hasOwnMetadata("metadataKey", p)); // true
console.log(Reflect.hasOwnMetadata("metadataKey1", p)); // false
// --------------Reflect.deleteMetadata --------- 移除
console.log(Reflect.deleteMetadata("metadataKey", p)); // true
console.log(Reflect.hasOwnMetadata("metadataKey", p)); // false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56