TypeScript类和JS范围混淆(再次)

时间:2016-09-12 12:28:16

标签: javascript typescript this

我认为JS范围不会让我再次惊讶,但我们在这里。

我正在使用此little JQuery plugin for observer like pattern。 这就是我订阅取消订阅来自自定义事件的处理程序(侦听器)的方式

$.observer.subscribe('my-event', this.myHandler);
$.observer.unsubscribe('my-event', this.myHandler);

public myHandler() {
    console.log("hello World", this);
}

问题在于,如果我使用类方法作为回调(this.myHandler),那么该方法不会在类范围内调用,而是在观察者对象范围内调用。

当我使用JQuery的代理方法时:

$.observer.subscribe('my-event', $.proxy(this.myHandler, this));
$.observer.unsubscribe('my-event', $.proxy(this.myHandler, this));

处理程序中的作用域是正确的,但取消订阅方法停止工作,显然使用代理我取消订阅其他内容,而不是处理程序方法。

我不能使用旧的JS技巧来定义局部变量并使用它来代替这个,比如

var o = this;
public myHandler() {
    console.log("hello World", o);
}

因为这是一个打字稿类,而var具有不同的含义。

我该怎么办?

2 个答案:

答案 0 :(得分:3)

将处理程序声明为属性应该起作用:

//public myHandler() {
public myHandler = () => {
    console.log("hello World", this);
}

这有副作用... myHandler是属性,无法覆盖。但是我们可以在我们的处理程序中调用另一个方法toBeOverriddenHandler,它具有适当的范围this并且可以被覆盖

public myHandler = () => {
    this.toBeOverriddenHandler()
}

// could be changed in subtypes
protected toBeOverriddenHandler () {
    console.log("hello World", this);
}

答案 1 :(得分:3)

发生这种情况的原因是因为每次调用它时$.proxy(this.myHandler, this)都会返回一个新函数。为了使unsubscribe能够工作,你需要传递与传递给subscribe的函数相同的函数(几乎所有的侦听器接口都是这种情况,包括DOM接口)。

const handler = $.proxy(this.myHandler, this);
$.observer.subscribe('my-event', handler);
$.observer.unsubscribe('my-event', handler);

或者,您可以在构造函数中将方法创建为箭头函数属性,或者自动绑定它:

class YourClass {
  constructor() {
    this.myHandler = () => {};
    // or
    this.myHandler = this.myHandler.bind(this);
  }
}

然后你可以将this.myHandler传递给observer.subscribe,它会做正确的事。