打字稿自定义装饰器:this的上下文

Posted

技术标签:

【中文标题】打字稿自定义装饰器:this的上下文【英文标题】:Typescript custom decorators : context of this 【发布时间】:2019-02-03 21:06:52 【问题描述】:

我正在创建一个自定义装饰器,它将在 RxJS 事件上运行装饰函数。

到目前为止一切顺利:当函数实际运行时,我的问题出现了:this 对象的上下文丢失了。

过去一天我一直在寻找解决方案,但似乎找不到。

Here is a stackblitz 重现问题。目标是在控制台中看到来自this.nameAngular

【问题讨论】:

【参考方案1】:

我在地图中传达方法上下文的自定义方式:)

return class extends constructor 
            constructor(...args) 
                super(...args);
                if(constructor.processCallbackMap)
                    Array.from(constructor.processCallbackMap).map(([key, value]) = 
                        constructor.processCallbackMap.set(key, value.bind(this));
                    );
                
            
        

【讨论】:

【参考方案2】:

请尝试以下代码,它会起作用。听说您只将其更改为构造函数。

function HelloWorld(): ClassDecorator 
  return function(constructor) 
    constructor.prototype.HelloWorld.apply(new constructor(), null);
  ;

【讨论】:

Hello world, name is HelloComponent 我已经更新了代码及其显示方式Hello world,名称是Angular。在构造函数的立场中添加了新的constructor() 这适用于一个简单的类,但这样做会丢失对前一个对象的所有内存引用,因为我实例化了一个新对象。此外,在服务是单例的情况下,这意味着我打破了设计模式。但它有效,我没有指定这些点是我的错,所以我会删除我的反对票!【参考方案3】:

在https://netbasal.com/inspiration-for-custom-decorators-in-angular-95aeb87f072c 没有

constructor.prototype.HelloWord.apply(this, null);

只需评论您的应用工作的那一行

cosntructor.prototype 用于可能使用 ngOnInit、ngOnChanges...

例如在页面中显示的是

import  environment  from "../environments/environment";
export function NgLog() : ClassDecorator 
  return function ( constructor : any ) 
    if( !environment.production ) 
      // You can add/remove events for your needs
      const LIFECYCLE_HOOKS = [
        'ngOnInit',
        'ngOnChanges',
        'ngOnDestroy'
      ];
      const component = constructor.name;

      LIFECYCLE_HOOKS.forEach(hook => 
        const original = constructor.prototype[hook];

        constructor.prototype[hook] = function ( ...args ) 
          console.log(`%c $component - $hook`, `color: #4CAF50; font-weight: bold`, ...args);
          original && original.apply(this, args);
        
      );
    

  

【讨论】:

函数名无关。我看到了他的作品并从中学习了装饰师。他所做的就是在函数中添加一个想要的行为。我想要做的是调用上述函数,而不是扩展它。【参考方案4】:

我看到您正在尝试在装饰器中调用装饰类实例的方法。然而,类装饰器不是这样工作的。它们在类被定义时被调用,而不是在它被实例化时被调用,所以你不能用你的类的实例调用任何东西。

这是您的updated stackblitz。我正在扩展您的类并在扩展类的构造函数中调用该方法,以便在实例化装饰类的对象时调用它。

【讨论】:

我明白了,扩展构造函数会成为问题吗? 而且您的解决方案似乎不太符合 lint 标准……我的项目对此非常严格,我将无法使用它。但是谢谢你的代码,我从中学到了一些东西,所以+1! 我设法使其符合 TSLint,是否可以获取初始构造函数的参数以将其添加到 super 调用中?我试过constructor.arguments,但它抛出'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them @trichetriche 可以在子类构造函数中接受...args并调用super(...args) 但是在哪里可以获得args

以上是关于打字稿自定义装饰器:this的上下文的主要内容,如果未能解决你的问题,请参考以下文章

打字稿方法返回未定义的方法装饰器

NestJS 的自定义路由装饰器

如何通过自定义装饰器记录@Input@Output值的值。

Spring异步线程池—传递线程上下文(TaskDecorator实现)

如何通过自定义装饰器提供非夹具 pytest 参数?

带有箭头功能的打字稿装饰器