Reflect
Reflect
const target = {
get foo() {
return this.bar;
},
bar: 3
};
const handler = {
get(target, propertyKey, receiver) {
if (propertyKey === "bar") return 2;
console.log(Reflect.get(target, propertyKey, receiver)); // this in foo getter references Proxy instance; logs 2
console.log(target[propertyKey]); // this in foo getter references "target" - logs 3
}
};
const obj = new Proxy(target, handler);
console.log(obj.bar); // 2
Reflect Metadata
所谓注解的定义就是:为相应的类附加元数据支持。所谓元数据可以简单的解释,就是修饰数据的数据,比如一个人有
function metadata(
metadataKey: any,
metadataValue: any
): {
(target: Function): void;
(target: Object, propertyKey: string | symbol): void;
};
@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'
内置Key
Type Metadata design:type
function logType(target: any, key: string) {
const t = Reflect.getMetadata("design:type", target, key);
console.log(`${key} type: ${t.name}`);
}
class Demo {
@logType // apply property decorator
public attr1: string;
}
// attr1 type: String
譬如在
function Prop(): PropertyDecorator {
return (target, key: string) => {
const type = Reflect.getMetadata("design:type", target, key);
console.log(`${key} type: ${type.name}`);
// other...
};
}
class SomeClass {
@Prop()
public Aprop!: string;
}
Parameter type metadata design:paramtypes
function logParamTypes(target: any, key: string) {
const types = Reflect.getMetadata("design:paramtypes", target, key);
const s = types.map(a => a.name).join();
console.log(`${key} param types: ${s}`);
}
class Foo {}
interface IFoo {}
class Demo {
@logParameters // apply parameter decorator
doSomething(
param1: string,
param2: number,
param3: Foo,
param4: { test: string },
param5: IFoo,
param6: Function,
param7: (a: number) => void
): number {
return 1;
}
}
// doSomething param types: String, Number, Foo, Object, Object, Function, Function
Return type metadata design:returntype
Reflect.getMetadata("design:returntype", target, key);
自定义metadataKey
除能获取类型信息外,常用于自定义
function classDecorator(): ClassDecorator {
return target => {
// 在类上定义元数据,key 为 `classMetaData`,value 为 `a`
Reflect.defineMetadata("classMetaData", "a", target);
};
}
function methodDecorator(): MethodDecorator {
return (target, key, descriptor) => {
// 在类的原型属性 'someMethod' 上定义元数据,key 为 `methodMetaData`,value 为 `b`
Reflect.defineMetadata("methodMetaData", "b", target, key);
};
}
@classDecorator()
class SomeClass {
@methodDecorator()
someMethod() {}
}
Reflect.getMetadata("classMetaData", SomeClass); // 'a'
Reflect.getMetadata("methodMetaData", new SomeClass(), "someMethod"); // 'b'
案例分析:Format
可以通过
const formatMetadataKey = Symbol("format");
function format(formatString: string) {
return Reflect.metadata(formatMetadataKey, formatString);
}
function getFormat(target: any, propertyKey: string) {
return Reflect.getMetadata(formatMetadataKey, target, propertyKey);
}
这里的Sysmbol("format")
class Greeter {
@format("Hello, %s")
name: string;
constructor(name: string) {
this.name = message;
}
sayHello() {
let formatString = getFormat(this, "name");
return formatString.replace("%s", this.name);
}
}
const g = new Greeter("Jony");
console.log(g.sayHello());
在上述中,我们在@Format("Hello, %s")
,返回一个装饰器函数,且该装饰器函数修饰了
案例分析:Angular 2 DI
type Constructor<T = any> = new (...args: any[]) => T;
const Injectable = (): ClassDecorator => target => {};
class OtherService {
a = 1;
}
@Injectable()
class TestService {
constructor(public readonly otherService: OtherService) {}
testMethod() {
console.log(this.otherService.a);
}
}
const Factory = <T>(target: Constructor<T>): T => {
// 获取所有注入的服务
const providers = Reflect.getMetadata("design:paramtypes", target); // [OtherService]
const args = providers.map((provider: Constructor) => new provider());
return new target(...args);
};
Factory(TestService).testMethod(); // 1