我认为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具有不同的含义。
我该怎么办?
答案 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
,它会做正确的事。