我正在尝试在使用参数初始化的类中使用装饰器,但是当将装饰器应用于我的函数时,构造函数中设置的值未定义。请参见下面的玩具示例:
@ExperimentalContracts
fun stuff() {
var possibleNull: String? = "test"
if (testNull(possibleNull)) {
mustPassNonNull(possibleNull)
}
}
fun mustPassNonNull(possibleNull: String) {
//use value that isn't null
}
@ExperimentalContracts
fun testNull(possibleNull: String?): Boolean {
contract{
returns(true) implies (possibleNull is String)
}
return possibleNull != null
}
我很想得到输出:
function someDecorator() {
return (target: any, _2: any, descriptor: PropertyDescriptor) => {
const func = descriptor.value.bind(target);
descriptor.value = () => {
console.log('Doing decorator stuff!');
func();
}
}
}
class Foo {
public constructor(private thing: string) { }
@someDecorator()
bar() {
console.log(this.thing);
}
}
new Foo('Hello world!').bar();
可惜我得到了输出:
> Doing decorator stuff!
> Hello world!
有人能指出我正确的方向吗?
答案 0 :(得分:2)
您获得的target
将是该类的原型,而不是任何实例。因此,将方法绑定到target
将会失去实际实例的this
上下文,而是在原型的上下文中调用它,而原型通常没有任何这些实例属性。
您必须等到实际调用类方法后才能获得适当的this
。因此,请忘记target
,而是将func
绑定到新方法中的this
上。并请注意,箭头函数将没有自己的this
,因此descriptor.value
不应是箭头函数(没有更多的箍跳)。因此,我建议使用传统的匿名function
。因此,将someDecorator()
的实现更改为以下内容:
function someDecorator() {
return (target: any, _2: any, descriptor: PropertyDescriptor) => {
const func = descriptor.value; // don't bind here
descriptor.value = function (...args: any) {
console.log('Doing decorator stuff!');
func.apply(this, args); // bind here (applying args is optional I guess)
}
}
}
现在应该可以使用:
new Foo('Hello world!').bar();
// Doing decorator stuff!
// Hello world!
希望有帮助。祝你好运!