如何使用非静态方法作为回调函数并引用“this”?

How to use non-static methods as callback functions and reference `this`?

提问人:jarnbjo 提问时间:10/12/2021 更新时间:10/12/2021 访问量:330

问:

基本上,我有以下 TypeScript 代码:

export class ClassA {

  method1() {
    this.method2(new ClassB().method3);
  }

  method2(functionReference: () => void) {
    functionReference();
  }

}

export class ClassB {

  method3() {
    this.method4();
  }

  method4() {
    console.log("method4 invoked");
  }

}

由于更熟悉其他OO编程语言(Java,C#,C++),我希望运行最终会导致in被调用。相反,我遇到了问题,即最终运行并且执行失败时未定义:new A().method1();method4ClassBthismethod3

TypeError:无法读取 undefined 的属性(读取“method4”)

我知道在 JavaScript 中工作所需的所有技巧,但我希望在 TypeScript 中的行为更加直观。只要是非静态方法,我就希望能够在方法中引用,无论从何处调用该方法。thismethod3this

TypeScript 中是否有不太繁琐的模式允许我使用非静态方法作为回调函数,就像我在这里尝试做的那样,或者只能使用静态方法?后者听起来并不正确,因为如果是这样,我希望编译器在我尝试将非静态方法作为函数引用传递时失败。this.method2(new ClassB().method3)

TypeScript 回调 这个

评论

0赞 jonrsharpe 10/12/2021
这回答了你的问题吗?如何在回调中访问正确的“this”
0赞 jarnbjo 10/12/2021
@jonrsharpe 不,忽略这个问题与 JavaScript 有关,如果我没有遗漏任何明显的东西,这个问题与我如何从回调函数 ClassB.method3 中访问(在 ClassA.method1 的上下文中)有关。我正在询问如何在 ClassB.method3 中使用(在 ClassB.method3 的上下文中)。thisthis
0赞 jonrsharpe 10/12/2021
你应该忽略这个问题与JavaScript有关! 在运行时,当 TypeScript 及其类型信息不再存在时,将解析。而你得到的上下文只是你.this.bind

答:

1赞 Teneff 10/12/2021 #1

您可以定义要将其引用作为类属性传递的方法

class ClassB {

  method3 = () => {
    this.method4();
  }

  method4() {
    console.log("method4 invoked");
  }

}

这样,它将在初始化时被定义为箭头函数,并且引用将被保留this

TS 游乐场

评论

1赞 jarnbjo 10/12/2021
非常感谢,尽管我更喜欢 Givi 的解决方案,因为我只需要更改使用该方法的代码,而不是在 ClassB 的实现中(这不一定是我的代码,但也可能来自包含的库)。
0赞 Teneff 10/12/2021
我对我的代码的唯一偏好是,您可以为库创建一个适配器,并且不必关心整个应用程序的实现
2赞 Givi 10/12/2021 #2

在 javascript 中,当您通过引用调用类方法时,它们不会绑定到其作用域。

如果将函数绑定到实例,或者将调用包装在函数中,则代码将正常工作。

如何重写类 ClassA 中的 method1 以使工作的一些示例。

将上下文绑定到函数:

  method1() {
    const instance = new ClassB();
    this.method2(instance.method3.bind(instance));
  }

结束通话:

  method1() {
    this.method2(()=>new ClassB().method3());
  }

评论

1赞 jarnbjo 10/12/2021
多谢。我已经尝试过类似的代码,甚至按照您的建议尝试了第二种方法,但没有让它起作用。问题是我在代码的其他地方有一个语法错误,如果你从 WebStorm 运行 Karma 测试并且编译器失败,你看不到编译器错误,但测试会以最后一个“良好”的编译结果重新运行。在修复不相关的代码问题之前,对可编译代码的更改不会产生影响。现在我甚至同时学到了两件事。