如何避免硬编码?在装饰器中
Posted
技术标签:
【中文标题】如何避免硬编码?在装饰器中【英文标题】:How to avoid hard coded this? in Decorators 【发布时间】:2015-07-31 12:42:31 【问题描述】:我已经阅读了 "How to implement a typescript decorator?" 和多个来源,但有些东西我无法用装饰器做。
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);
在foo
中记录到控制台
console.log(this, "bar", arg);
将字符串 "FooBar foo: function, bar: function bar test"
记录在控制台中,bar
。
现在让我们使用装饰器:
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;
;
我们使用相同的功能,但装饰:
class FooBar
@log
public foo(arg): void
console.log(this);
this.bar(arg);
@log
private bar(arg) : void
console.log(this, "bar", arg);
我们像以前一样调用foo
:
var foobarFoo = new FooBar();
foobarFooBar.foo("test");
对象Window
被console.log(this);
登录到控制台foo
并且bar
永远不会被foo
调用,因为this.bar(arg);
会导致Uncaught TypeError: this.bar is not a function
。
问题在于log
装饰器内部的硬编码this
:
value.value.apply(this, args);
如何保存原来的this
值?
【问题讨论】:
【参考方案1】:相信你可以使用
var self = this;
为了在该特定点保留“this”。然后,只需在稍后您想要特定的this
的地方使用self
【讨论】:
感谢您尝试回答,但使用装饰器时,我无法控制特定点【参考方案2】:不要使用箭头函数。使用函数表达式:
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;
;
这样在调用 log 时它将使用函数的 this
上下文而不是 this
的值。
顺便说一句,我建议编辑描述符/值参数并返回它,而不是通过返回一个新的描述符来覆盖它。这样你就可以保留当前描述符中的属性,并且不会覆盖另一个装饰器可能对描述符所做的事情:
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;
More details in this answer - 请参阅“示例 - 无参数 > 注释”下的“坏与好”示例
【讨论】:
感谢您的回答,我没有注意到我正在使用箭头函数。 @OweRReLoaDeD 是的,很容易错过。直到我在操场上弹出它并看到 javascript 正在执行_this
时我才注意到
OP 的代码似乎来自我的博客文章 - smellegantcode.wordpress.com/2015/04/02/… - 我会更新它! :)
我也有这个问题儿子在blog.wolksoftware.com/…blog.wolksoftware.com/…更新了一篇博文
很好的例子!一个挑剔:似乎target
的类型应该是Object
而不是Function
,因为它是类的原型。以上是关于如何避免硬编码?在装饰器中的主要内容,如果未能解决你的问题,请参考以下文章