【问题标题】:How to use a TypeScript method decorator and retain normal `this` scope如何使用 TypeScript 方法装饰器并保留正常的 `this` 范围
【发布时间】:2019-10-04 23:14:33
【问题描述】:

请注意:这个问题是因为在运行我的修饰方法时使用了 GraphQL 解析器。这意味着this 的范围是undefined。但是,这个问题的基础知识对于遇到装饰器问题的任何人都很有用。


这是我想要使用的基本装饰器(我的有更多代码):

const someDecorator = (argPassed: any) => {

  return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {

    const originalMethod = descriptor.value;

    // DO stuff here...
    console.log(argPassed);

    // Wrapping the original method
    descriptor.value = (...args: any[]) => {

      const result = originalMethod.apply(this, args);

      return result;
    };
  };
};

我在装饰器中使用箭头函数,这是我可以让它返回某种范围的唯一方法,尽管与普通的 this 范围不同。

这是我正在使用的类和我正在装饰的方法:

class SomeClass {

  constructor() {
  }

  @someDecorator('Passing this in...')
  public doingSomething(argPassed: string) {

    console.log(this); // Returns: { default: SomeClass { otherMethodInMyClass: [Function] } }

    //  Meaning i can't do this
    //  this.otherMethodInMyClass is not a function
    this.otherMethodInMyClass(argPassed);

  }

  private otherMethodInMyClass = (argPassed: any) => {
    // Let's go for it...
  }

}

目前装饰器将doingSomething的作用域传回为:

{ default: SomeClass { otherMethodInMyClass: [Function] } }

当我不使用装饰器时:

SomeClass { doingSomething: [Function], otherMethodInMyClass: [Function] }

这是正常行为吗?如果没有,我做错了什么? 如果是这样,我如何允许我的方法在调用其他方法之后使用它自己的范围。

更新: 正如@jcalz 正确提到的,箭头函数没有自己的this 上下文。但是,当我在装饰器上使用非箭头函数时,this 返回为undefined

提前致谢

【问题讨论】:

  • 不要使用箭头函数作为方法,因为an arrow function does not get its own this context。请改用常规匿名函数。
  • 感谢@jcalz,我尝试不使用箭头函数,但结果未定义。
  • 另外@jcalz,如果您有一个工作示例,其中返回正确的上下文,请将其作为答案!

标签: typescript ts-node typescript-decorator


【解决方案1】:

在使用类的方法作为 GraphQL 解析器时我遇到了同样的问题,我能够解决这个问题的唯一方法是将类用作单例,然后从单例中调用其他私有方法这个

【讨论】:

    【解决方案2】:

    您问题中的问题似乎是您使用箭头函数作为方法,因为arrow functions don't get their own this context 是不可取的。

    您接着说更改此设置并不能解决您的问题,但我无法重现:

    const someDecorator = (argPassed: any) => {
        return (target: any, propertyKey: string, descriptor: PropertyDescriptor) => {
            const originalMethod = descriptor.value;
            console.log("ARGPASSED: ");
            console.log(argPassed);
            // anonymous function, not arrow
            descriptor.value = function (...args: any[]) {
                const result = originalMethod.apply(this, args);
                return result;
            };
        };
    };
    
    class SomeClass {    
        constructor() { }
    
        @someDecorator('Passing this in...')
        public doingSomething(argPassed: string) {   
            console.log("THIS: ")
            console.log(this); 
            this.otherMethodInMyClass(argPassed);
        }
    
        private otherMethodInMyClass = (argPassed: any) => { }
    }
    
    new SomeClass().doingSomething("abc");
    // ARGPASSED: 
    // Passing this in...
    // THIS: 
    // Object { otherMethodInMyClass: otherMethodInMyClass() }
    

    Link to code in Playground

    我觉得不错。如果您的问题仍然存在,您可能希望在问题中包含有关您的配置的更多详细信息。确保问题中的代码构成reproducible example 总是有帮助的。祝你好运!

    【讨论】:

    • 我已将此标记为答案,因为它回答了我提出的问题。我现在已经弄清楚实际问题是我调用我的方法的方式。我将它称为 GraphQL 解析器的一部分,它在方法运行之前更改范围。所以当直接运行时,thisdefined,当通过解析器运行时 thisundefined。感谢您的帮助@jcalz。
    • 这里只是一个奇怪的问题,如果我将这里的this 替换为target 会怎样? const result = originalMethod.apply(this -> target, args);
    • 您可以try it 看看它不起作用。
    猜你喜欢
    • 2019-05-19
    • 1970-01-01
    • 2015-06-04
    • 2014-10-08
    • 1970-01-01
    • 2022-09-29
    • 2020-08-23
    • 2019-01-14
    • 2012-02-18
    相关资源
    最近更新 更多