问题描述
我已阅读和多个来源,但我有一些东西,也没有能够装饰。
I have read "How to implement a typescript decorator?" and multiple sources but there is something that i have nor been able to do with decorators.
class FooBar {
public foo(arg): void {
console.log(this);
this.bar(arg);
}
private bar(arg) : void {
console.log(this, "bar", arg);
}
}
如果我们调用函数 foo
:
var foobar = new FooBar();
foobar.foo("test");
控制台中记录了对象 FooBar
通过 console.log(this);
in foo
The object FooBar
is logged in the console by console.log(this);
in foo
字符串FooBar {foo:function,bar:function} bar test
由 console.log记录在控制台中(这个,bar ,arg);
in bar
。
现在让我们使用装饰器:
Now let's use a decorator:
function log(target: Function, key: string, value: any) {
return {
value: (...args: any[]) => {
var a = args.map(a => JSON.stringify(a)).join();
var result = value.value.apply(this, args); // How to avoid hard coded this?
var r = JSON.stringify(result);
console.log(`Call: ${key}(${a}) => ${r}`);
return result;
}
};
}
我们使用相同的功能但装饰:
We use the same function but decorated:
class FooBar {
@log
public foo(arg): void {
console.log(this);
this.bar(arg);
}
@log
private bar(arg) : void {
console.log(this, "bar", arg);
}
}
我们调用 foo
正如我们之前所做的那样:
And we invoke foo
as we did before:
var foobarFoo = new FooBar();
foobarFooBar.foo("test");
控制台中记录了对象 Window
通过 console.log(this);
in foo
The objectWindow
is logged in the console by console.log(this);
in foo
bar
永远不会被 foo
调用,因为 this.bar(arg);
导致未捕获TypeError:this.bar不是函数
。
And bar
is never invoked by foo
because this.bar(arg);
causes Uncaught TypeError: this.bar is not a function
.
问题是硬编码
:日志
装饰者内的
The problem is the hardcoded this
inside the log
decorator:
value.value.apply(this, args);
如何保存原始此
值?
推荐答案
不要使用箭头功能。使用函数表达式:
Don't use an arrow function. Use a function expression:
function log(target: Object, key: string, value: any) {
return {
value: function(...args: any[]) {
var a = args.map(a => JSON.stringify(a)).join();
var result = value.value.apply(this, args);
var r = JSON.stringify(result);
console.log(`Call: ${key}(${a}) => ${r}`);
return result;
}
};
}
这样它会使用函数的这个上下文而不是
此
的值。
That way it will use the function's
this
context instead of the value of this
when log is called.
顺便说一句,我建议编辑descriptor / value参数并返回,而不是通过返回一个新的描述符来覆盖它。这样你就可以保留当前属性中的属性,并且不会覆盖另一个装饰者可能对描述符做的事情:
By the way, I would recommend editing the descriptor/value parameter and return that instead of overwriting it by returning a new descriptor. That way you keep the properties currently in the descriptor and won't overwrite what another decorator might have done to the descriptor:
function log(target: Object, key: string, descriptor: TypedPropertyDescriptor<any>) {
var originalMethod = descriptor.value;
descriptor.value = function(...args: any[]) {
var a = args.map(a => JSON.stringify(a)).join();
var result = originalMethod.apply(this, args);
var r = JSON.stringify(result);
console.log(`Call: ${key}(${a}) => ${r}`);
return result;
};
return descriptor;
}
- 请参阅示例 - 没有参数>注释下的Bad vs Good示例
More details in this answer - See the "Bad vs Good" example under "Example - Without Arguments > Notes"
这篇关于如何避免硬编码?在装饰者的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!