跳到主要内容

README

什么是原数据

元数据 :用来描述数据的数据,在我们的程序中,对象、类 等都是数据,它们描述了某种数据

另外还有一种数据,它可以用来描述 对象、类,这些用来描述数据的数据就是 元数据

比如一首歌曲本身就是一组数据,同时还有一组用来描述歌曲的歌手、格式、时长的数据,那么这组数据就是歌曲数据的元数据

在 装饰器 函数中 ,我们可以拿到 类、方法 、访问符、属性、参数 的基本信息,如它们的名称,描述符 等

但是我们想获取更多信息就需要通过另外的方式来进行:元数据

Reflect反射原信息

Reflect 是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法与proxy handlers (en-US)的方法相同。Reflect不是一个函数对象,因此它是不可构造的。

定义元数据

我们可以 类、方法 等数据定义元数据

元数据会被附加到指定的 类、方法 等数据之上,但是又不会影响 类、方法 本身的代码

设置

Reflect.defineMetadata(metadataKey, metadataValue, target, propertyKey)

  • metadataKey:meta 数据的 key
  • metadataValue:meta 数据的 值
  • target:meta 数据附加的目标
  • propertyKey(可选):对应的 property key

获取

Reflect.getMetadata(metadataKey, target, propertyKey)、

class A {
public static method1() {
}

public method2() {
}
}

let obj = new A;

Reflect.defineMetadata("n", 1, A);
Reflect.defineMetadata("n", 2, A, "method1");
Reflect.defineMetadata("n", 3, obj);
Reflect.defineMetadata("n", 4, A, "method2");

console.log(Reflect.getMetadata("n", A));
console.log(Reflect.getMetadata("n", A, "method1"))
console.log(Reflect.getMetadata("n", obj))
console.log(Reflect.getMetadata("n", obj, "method2"))

和修饰器结合使用简化操作

@Reflect.metadata('inClass', 'A')
class Test {
@Reflect.metadata('inMethod', 'B')
public hello(): string {
return 'hello world';
}
}

console.log(Reflect.getMetadata('inClass', Test)); // 'A'
console.log(Reflect.getMetadata('inMethod', new Test(), 'hello')); // 'B'
// 参数装饰器使用反射 api 存储被装饰参数的索引
export function logParameter(target: Object, propertyName: string, index: number) {
// 获取目标对象的元信息
const indices = Reflect.getMetadata(`log_${propertyName}_parameters`, target, propertyName) || [];
indices.push(index);
// 定义目标对象的元信息
Reflect.defineMetadata(`log_${propertyName}_parameters`, indices, target, propertyName);
}

// 属性装饰器使用反射 api 获取属性的运行时类型
export function logProperty(target: Object, propertyName: string): void {
// 获取对象属性的设计类型
var t = Reflect.getMetadata("design:type", target, propertyName);
console.log(`${propertyName} type: ${t.name}`); // name type: String
}


class Employee {
@logProperty
private name: string;

constructor(name: string) {
this.name = name;
}

greet(@logParameter message: string): string {
return `${this.name} says: ${message}`;
}
}

上面的代码用到了 reflect-metadata 这个库。其中,我们使用了反射元信息的设计键(例如:design:type)。目前只有三个:

  • 类型元信息用了元信息键 design:type。
  • 参数类型元信息用了元信息键 design:paramtypes。
  • 返回类型元信息用了元信息键 design:returntype。

有了反射,我们就能够在运行时得到以下信息:

  • 实体名。
  • 实体类型。
  • 实体实现的接口。
  • 实体构造器参数的名称和类型。