分类:
装饰器的执行分为两个阶段。
(1)评估(evaluation):计算@
符号后面的表达式的值,得到的应该是函数。
(2)应用(application):将评估装饰器后得到的函数,应用于所装饰对象。
也就是说,装饰器的执行顺序是,先评估所有装饰器表达式的值,再将其应用于当前类。
应用装饰器时,顺序依次为方法装饰器和属性装饰器,然后是类装饰器。
function d(str:string) {
console.log(`评估 @d(): ${str}`);
return (
value:any, context:any
) => console.log(`应用 @d(): ${str}`);
}
function log(str:string) {
console.log(str);
return str;
}
@d('类装饰器')
class T {
@d('静态属性装饰器')
static staticField = log('静态属性值');
@d('原型方法')
[log('计算方法名')]() {}
@d('实例属性')
instanceField = log('实例属性值');
@d('静态方法装饰器')
static fn(){}
}
评估 @d(): 类装饰器
评估 @d(): 静态属性装饰器
评估 @d(): 原型方法
计算方法名
评估 @d(): 实例属性
评估 @d(): 静态方法装饰器
应用 @d(): 静态方法装饰器
应用 @d(): 原型方法
应用 @d(): 静态属性装饰器
应用 @d(): 实例属性
应用 @d(): 类装饰器
静态属性值
可以看到,类载入的时候,代码按照以下顺序执行。
(1)装饰器评估:这一步计算装饰器的值,首先是类装饰器,然后是类内部的装饰器,按照它们出现的顺序。
注意,如果属性名或方法名是计算值(本例是“计算方法名”),则它们在对应的装饰器评估之后,也会进行自身的评估。
(2)装饰器应用:实际执行装饰器函数,将它们与对应的方法和属性进行结合。
静态方法装饰器首先应用,然后是原型方法的装饰器和静态属性装饰器,接下来是实例属性装饰器,最后是类装饰器。
注意,“实例属性值”在类初始化的阶段并不执行,直到类实例化时才会执行。
如果一个方法或属性有多个装饰器,则内层的装饰器先执行,外层的装饰器后执行。