什么是装饰器?
在 TypeScript 中,装饰器是一种特殊语法,可以用于修饰类、方法、属性和参数。它们通过 @
语法定义,是由函数实现的。装饰器主要通过元编程机制,为代码提供增强功能。
装饰器的分类
- 类装饰器(Class Decorators) :应用于类构造函数,可以用于修改类的定义。
- 方法装饰器(Method Decorators) :应用于方法,可以用于修改方法的行为。
- 访问器装饰器(Accessor Decorators) :应用于类的访问器属性(getter 或 setter)。
- 属性装饰器(Property Decorators) :应用于类的属性。
- 参数装饰器(Parameter Decorators) :应用于方法参数。
装饰器名称 | 装饰器描述 | 装饰器的参数说明 |
---|---|---|
类装饰器(Class Decorators) | 应用于类构造函数,可以用于修改类的定义。 | constructor: Function |
方法装饰器(Method Decorators) | 应用于方法,可以用于修改方法的行为。 | target: Object, propertyKey: string, descriptor: PropertyDescriptor |
访问器装饰器(Accessor Decorators) | 应用于类的访问器属性(getter 或 setter)。 | target: Object, propertyKey: string, descriptor: PropertyDescriptor |
属性装饰器(Property Decorators) | 应用于类的属性。 | target: Object, propertyKey: string |
参数装饰器(Parameter Decorators) | 应用于方法参数。 | target: Object, propertyKey: string, parameterIndex: number |
装饰器的特点
- 装饰器是语法糖,本质上是一个函数。
- 装饰器通常返回一个函数,用来替换或增强目标代码。
- 装饰器执行的顺序是从下到上,从外到内(从最近作用域开始解析)。
类装饰器
当类装饰器有返回值时,返回的值会替换原有的类的定义。
// @ts-nocheck
function Liu(cls: any) {
cls.prototype.id = "1";
}
function ReturnDecorator(name: string) {
console.log('ReturnDecorator');
return function (target: any) {
// 这里 target
console.log(name);
};
}
@Liu
@ReturnDecorator('lsp')
class Name { }
const name = new Name()
console.log(name.id) // liu
// ReturnDecorator
// lsp
// 1
装饰器工厂
可以传入参数进去
// @ts-nocheck
function Liu(cls: string) {
// cls hello
return function (target: any,) {
// param Name
target.prototype.liu = cls;
target.prototype.s = cls;
};
}
@Liu('hello')
class Name { }
const name = new Name()
console.log(name.liu) // hello
console.log(name.s) // hello
属性装饰器 也可以用作函数
参数3: 成员的属性描述符,详见 descriptor
添加 get 注意 不能直接使用 cls[key] 会无限循环调用的,需要映射
function Log(prefix: string) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const original = descriptor.value;
descriptor.value = function (...args: any[]) {
console.log(`${prefix} 调用方法: ${propertyKey}`);
return original.apply(this, args);
};
};
}
class Example {
@Log("DEBUG")
sayHello() {
console.log("Hello, world!");
}
}
new Example().sayHello();
参数装饰器
// @ts-nocheck
function Liu(num) {
console.log(num); // 100
return function (target: any, propertyKey, index) {
// cls 类型 key: a 参数名字,index: 0 参数索引
console.log(target, propertyKey, index, "aaa");
};
}
class Name {
fun(@Liu(100) a: string) {
console.log(a); // 123
}
}
// 输出
// 100
// {} fun 0 aaa
装饰器类型
ClassDecorator
是类装饰器,用于装饰类。PropertyDecorator
是属性装饰器,用于装饰类的属性。MethodDecorator
是方法装饰器,用于装饰类的方法。ParameterDecorator
是参数装饰器,用于装饰类方法的参数。
装饰器执行顺序
- 首先执行实例相关:参数装饰器 > 方法装饰器 > 类装饰器 > 属性装饰器
- 然后执行静态相关:参数装饰器 > 方法装饰器 > 类装饰器 > 属性装饰器
- 多个装饰器装饰同一个数据时,从下往上依次执行
- 结果从上往下应用(函数返回的最终结果)。
function DecoratorA() {
console.log("DecoratorA evaluated");
return function (target: any) {
console.log("DecoratorA executed");
};
}
function DecoratorB() {
console.log("DecoratorB evaluated");
return function (target: any) {
console.log("DecoratorB executed");
};
}
@DecoratorA()
@DecoratorB()
class Example {}
// 输出
// DecoratorA evaluated
// DecoratorB evaluated
// DecoratorB executed
// DecoratorA executed