浅谈Typescript 装饰器执行顺序
TypeScript 中装饰器的执行顺序遵循一套固定的规则,可以从同一声明上的多个装饰器和类中不同成员的装饰器两个维度来理解。
1. 同一声明上多个装饰器的顺序
当一个声明(如类、方法、属性)上应用了多个装饰器时:
- 装饰器表达式(工厂函数)的求值顺序:从上到下。
- 装饰器函数(返回的函数本身)的执行顺序:从下到上。
function first() {
console.log('first(): 工厂求值');
return function (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) {
console.log('first(): 装饰器执行');
};
}
function second() {
console.log('second(): 工厂求值');
return function (target: any, propertyKey?: string, descriptor?: PropertyDescriptor) {
console.log('second(): 装饰器执行');
};
}
class Example {
@first()
@second()
method() {}
}
输出顺序:
first(): 工厂求值
second(): 工厂求值
second(): 装饰器执行
first(): 装饰器执行
2. 类中不同成员装饰器的整体顺序
对于类中的不同成员(属性、方法、参数等),装饰器的执行顺序由成员类型和所属(实例/静态)决定,与源代码书写顺序无关。
整体求值顺序如下:
- 实例成员:先参数装饰器,再方法/访问器/属性装饰器。
对于每个实例成员,按照它们在类中出现的从上到下顺序处理。 - 静态成员:同样先参数装饰器,再方法/访问器/属性装饰器。
对于每个静态成员,按照它们在类中出现的从上到下顺序处理。 - 构造函数参数装饰器。
- 类装饰器(最后执行)。
可以浓缩成一句话:实例 → 静态 → 构造参数 → 类,每一组内部按成员的源代码顺序,且每个成员内是参数装饰器优先于该成员的属性/方法/访问器装饰器。
3. 示例演示
function classDecorator() {
console.log('类装饰器工厂');
return function (constructor: Function) {
console.log('类装饰器执行');
};
}
function propertyDecorator(name: string) {
console.log(`属性装饰器工厂: ${name}`);
return function (target: any, propertyKey: string) {
console.log(`属性装饰器执行: ${name}`);
};
}
function methodDecorator(name: string) {
console.log(`方法装饰器工厂: ${name}`);
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
console.log(`方法装饰器执行: ${name}`);
};
}
function parameterDecorator(name: string) {
console.log(`参数装饰器工厂: ${name}`);
return function (target: any, propertyKey: string, parameterIndex: number) {
console.log(`参数装饰器执行: ${name}`);
};
}
@classDecorator()
class Demo {
@propertyDecorator('实例属性')
instanceProp: string;
@propertyDecorator('静态属性')
static staticProp: string;
constructor(@parameterDecorator('构造参数') param: string) {
this.instanceProp = param;
}
@methodDecorator('实例方法')
instanceMethod(@parameterDecorator('实例方法参数') arg: number) {}
@methodDecorator('静态方法')
static staticMethod(@parameterDecorator('静态方法参数') arg: number) {}
}
运行这段代码,控制台输出顺序如下:
属性装饰器工厂: 实例属性
属性装饰器执行: 实例属性 // 实例属性,无参数装饰器
方法装饰器工厂: 实例方法
参数装饰器工厂: 实例方法参数
参数装饰器执行: 实例方法参数 // 实例方法参数优先
方法装饰器执行: 实例方法 // 实例方法在后属性装饰器工厂: 静态属性
属性装饰器执行: 静态属性 // 静态属性
方法装饰器工厂: 静态方法
参数装饰器工厂: 静态方法参数
参数装饰器执行: 静态方法参数 // 静态方法参数优先
方法装饰器执行: 静态方法 // 静态方法在后参数装饰器工厂: 构造参数
参数装饰器执行: 构造参数 // 构造函数参数类装饰器工厂
类装饰器执行 // 类装饰器最后
4. 总结要点
- 同一成员多装饰器:工厂自上而下求值,装饰器自下而上执行。
- 多成员:先处理实例成员(从上到下),再处理静态成员(从上到下),然后构造函数参数,最后类装饰器。
到此这篇关于浅谈Typescript 装饰器执行顺序的文章就介绍到这了,更多相关Typescript 装饰器执行顺序内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
相关文章
论Bootstrap3和Foundation5网格系统的异同
这篇文章主要介绍了Bootstrap3和Foundation5网格系统,网格的基本构造,如何构建的,描述它们的主要部件,以及它们对不同屏幕的大小表现出的差异,感兴趣的小伙伴们可以参考一下2016-05-05
Safari 中 filter: blur() 高斯模糊引发的性能问题及解决方案
在Safari浏览器中使用CSS滤镜如filter:blur()时,可能会遇到性能问题,如页面卡顿和小方块现象,这些问题通常与渲染机制和硬件加速的缺失有关,通过开启硬件加速,如使用transform:translate3d(0,0,0),可以有效解决这些问题,并提升用户体验2024-10-10


最新评论