装饰器:(Decorator)
装饰器是一种特殊类型的声明,它能够被附加到类声明,方法,访问符,属性或参数上。 装饰器使用@teacher这种形式,teacher必须是一个函数,它会在运行时被调用,被装饰的声明信息做为参数传入。
根据被装饰的对象不同,装饰器分为以下几类:
类装饰器:
//定义类装饰器
function teacher(target: Function) {
console.log(target)
}
//语法糖使用
@teacher
class Person {}
//实质上的调用
class Person {}
teacher(Person);
控制台输出
[Function teacher]
只有一个参数:target为装饰类的构造函数。
方法装饰器:
function teacher(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log('target ', target);
console.log('propertyKey ', propertyKey);
console.log('descriptor ', descriptor);
}
//语法糖使用
class Person {
@teacher
demo() {
console.log('demo');
}
}
//实质上的调用
teacher(Person.prototype/Person,'domo',方法的描述符)
控制台输出
target { demo: [Function (anonymous)] }
// target [Function: Person] { demo: [Function (anonymous)] } 静态方法输出
propertyKey demo
descriptor {
value: [Function (anonymous)],
writable: true,
enumerable: true,
configurable: true
}
propertyKey demo
descriptor {
value: [Function (anonymous)],
writable: true,
enumerable: true,
configurable: true
}
3个参数:
- 类的原型对象,如果是静态方法则为类的构造函数
- 方法名称
- 方法的属性描述符
属性装饰器:
属性装饰器多用在属性依赖注入上面。属性装饰器接收两个参数:
- 类的原型对象,如果是静态方法则为类的构造函数
- 属性名
function demo(value: string) {
return function(target: any, propertyKey: string) {
target[propertyKey] = value;
}
}
class Demo {
@demo('haha') name?: string;
}
const d = new Demo();
console.log(d.name);
函数参数装饰器:
参数装饰器表达式会在运行时当作函数被调用,传入下列3个参数:
- 对于静态成员来说是类的构造函数,对于实例成员是类的原型对象。
- 参数的名字。
- 参数在函数参数列表中的索引。
function PathParam(paramDesc: string) {
return function (target: any, paramName: string, paramIndex: number) {
!target.$meta && (target.$meta = {});
target.$meta[paramIndex] = paramDesc;
}
}
class Demo {
constructor() { }
getUser( @PathParam("userId") userId: string) { }
}
console.log((<any>Demo).prototype.$meta);
工厂模式
装饰器工厂
装饰器工厂也是一个函数,只不过它的返回值是一个装饰器,装饰器工厂在使用时可以传参,普通装饰器不可以。例:
function event(eventName: string) {
return function(target: any) {
// 获取到当前eventName和被装饰对象进行操作
}
}
使用
@event('chifan')
Class person {
}
装饰器执行顺序:
- 装饰器工厂需要先求值,再装饰,求值顺序是由上到下
- 装饰器可以直接求值,装饰顺序是由下到上
装饰器与继承的区别
装饰器可叠加使用