我有一个类装饰器,该类装饰器更改了类并在其中添加了一个属性。 然后,我有一个方法装饰器,该装饰器位于具有该类装饰器的类中,并且该方法装饰器正在尝试访问由另一个装饰器创建的类中的属性。
// The Class Decorator
export function SomeDecorator(): ClassDecorator {
return target => {
target['property'] = { text: 'some text' };
return target;
}
}
// The Method Decorator
export function SomeOtherDecorator(): MethodDecorator {
return (target, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
console.log(target['property'].text);
}
}
// The Class
@SomeDecorator()
export class SomeClass {
@SomeOtherDecorator()
someMethod() {}
}
它将在运行时对此进行回答: TypeError:无法读取未定义的属性“文本”
为什么?
答案 0 :(得分:0)
就像提香说的那样,类装饰器在方法装饰器之后运行,这就是您的示例代码console.log(target['property'].text);
失败的原因。
不确定您的实际用例,但是如果您可以推迟对target['property']
的访问,则不会有任何问题。
function SomeOtherDecorator(): MethodDecorator {
return (target, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
const fn = descriptor.value;
// no problem, because `target['property']` is only accessed
// when the decorated method (not decorator) is called.
descriptor.value = (...args) => {
console.log(target['property'].text);
return fn.apply(target, args);
};
}
}
您甚至可以使用getter来惰性运行装饰器,应注意大多数用例。
function SomeOtherDecorator(): MethodDecorator {
return (target, propertyKey: string, propertyDescriptor: PropertyDescriptor) => {
const fn = descriptor.value;
let decoratedFn;
descriptor.get = () => {
if (decoratedFn) return decoratedFn;
// do whatever you want to decorate the method/fn
// including access to `target['property']`
decoratedFn = ...
}