Javascript 在绑定方法中获取类的this上下文,同时保留绑定
我正在为addEventListener创建一个小助手类。我遇到的问题是,我无法有效地获取类的this上下文和事件的this上下文(附加的事件目标) (1) 如果我使用arrow函数,我可以得到类的this,但是我不能得到绑定的this(通过function.prototype.call) (2) 如果我使用一个函数表达式,我可以得到这个绑定,但是我不能访问这个类 (3) 我也不能使用内部闭包。函数/方法必须从外部范围引用 这是一个简单的例子来告诉你我的意思。有没有办法勾选所有方框?我所能想到的就是创建另一个helper类,该类将为附加的每个事件侦听器初始化,但如果有更简单的方法,这似乎不是很有效Javascript 在绑定方法中获取类的this上下文,同时保留绑定,javascript,typescript,dom-events,Javascript,Typescript,Dom Events,我正在为addEventListener创建一个小助手类。我遇到的问题是,我无法有效地获取类的this上下文和事件的this上下文(附加的事件目标) (1) 如果我使用arrow函数,我可以得到类的this,但是我不能得到绑定的this(通过function.prototype.call) (2) 如果我使用一个函数表达式,我可以得到这个绑定,但是我不能访问这个类 (3) 我也不能使用内部闭包。函数/方法必须从外部范围引用 这是一个简单的例子来告诉你我的意思。有没有办法勾选所有方框?我所能想到的
class EventListenerHelper {
private targets: Array<EventTarget>
constructor() {
// If there was a single target, it would be very easy. But there are multiple
this.targets = [
document.body,
window
];
}
/**
* (1) - Try to use an arrow function
*
* This falls short because it's not possible to get the this context of the Event
*/
private attachWithArrowFunction() {
this.targets.forEach((target) => {
target.addEventListener('click', this.listenerCallbackArrow, false);
});
}
private listenerCallbackArrow = (e: Event) => {
// Cannot get event this
const eventThis = undefined;
// Note that e.target is the innermost element which got hit with the event
// We are looking for that target that had the event listener attached
// If I'm not mistaken, the only way to get it is from the this context
// which is bound to the event callback
this.processListener(eventThis, e);
}
/**
* (2) - Try to use a regular class method
*
* This falls short because it's not possible to get the this context of the class
*/
private attachWithClassMethod() {
this.targets.forEach((target) => {
target.addEventListener('click', this.listenerCallbackMethod, false);
});
}
private listenerCallbackMethod(e: Event) {
// Here we have the eventThis
const eventThis = this;
// But the class instance is completely unreachable
}
/**
* (3) - Try to create a closure wrapper
*
* This almost works, but it's not possible to removeEventListener later
*/
private attachWithClosure() {
let self = this;
this.targets.forEach((target) => {
target.addEventListener('click', function(e: Event) {
self.processListener(this as EventTarget, e);
}, false);
});
}
private processListener(eventThis: EventTarget, e: Event) {
// Do some stuff with other class methods
//
}
private detach() {
this.targets.forEach((target) => {
target.addEventListener('click', this.listenerCallbackArrow, false);
});
}
}
类EventListenerHelper{
私有目标:数组
构造函数(){
//如果只有一个目标,那就很容易了。但是有多个目标
这一点。目标=[
文件正文,
窗口
];
}
/**
*(1)-尝试使用箭头功能
*
*这是不够的,因为无法获取事件的上下文
*/
私有AttachWithArrow函数(){
this.targets.forEach((target)=>{
target.addEventListener('click',this.listenerCallbackArrow,false);
});
}
私有listenerCallbackArrow=(e:Event)=>{
//无法获取此事件
const eventThis=未定义;
//注意,e.target是事件命中的最内层元素
//我们正在寻找连接了事件侦听器的目标
//如果我没有弄错的话,唯一的方法就是从这个上下文中得到它
//它绑定到事件回调
this.processListener(eventThis,e);
}
/**
*(2)-尝试使用常规类方法
*
*这是不够的,因为不可能获得类的上下文
*/
私有attachWithClassMethod(){
this.targets.forEach((target)=>{
target.addEventListener('click',this.listenerCallbackMethod,false);
});
}
私有listenerCallbackMethod(e:事件){
//这是我们今天的活动
const eventThis=this;
//但是类实例是完全不可访问的
}
/**
*(3)-尝试创建闭包包装器
*
*这几乎可以正常工作,但以后不可能删除VentListener
*/
私人attachWithClosure(){
让自我=这个;
this.targets.forEach((target)=>{
target.addEventListener('click',函数(e:事件){
processListener(作为EventTarget,e);
},假);
});
}
私有processListener(eventThis:EventTarget,e:Event){
//用其他类方法做一些事情
//
}
私家侦探(){
this.targets.forEach((target)=>{
target.addEventListener('click',this.listenerCallbackArrow,false);
});
}
}
处理此问题的常用方法是返回函数:
private attach() {
const listener = this.getListener()
this.targets.forEach(target => {
target.addEventListener('click', listener, false)
})
}
private getListener() {
const self = this
return function (e: Event) {
// self if EventListenerHelper this
// this is Event this
}
}
但我看不出它有什么好处,因为传递给addEventListener
的函数中的this
等于event.currentTarget
,因此您可以绑定侦听器并使用该属性,而不是this
:
constructor() {
// ...
this.listener = this.listener.bind(this)
}
private listener(e) {
// this is EventListenerHelper this
// e.currentTarget is Event this
}
处理此问题的常用方法是返回函数:
private attach() {
const listener = this.getListener()
this.targets.forEach(target => {
target.addEventListener('click', listener, false)
})
}
private getListener() {
const self = this
return function (e: Event) {
// self if EventListenerHelper this
// this is Event this
}
}
但我看不出它有什么好处,因为传递给addEventListener
的函数中的this
等于event.currentTarget
,因此您可以绑定侦听器并使用该属性,而不是this
:
constructor() {
// ...
this.listener = this.listener.bind(this)
}
private listener(e) {
// this is EventListenerHelper this
// e.currentTarget is Event this
}
因此,如果您需要这两个上下文,为什么不指定一个变量-self=this。这是因为这样我就无法引用闭包之外的函数。请参阅代码中的(3)个案例。简单。让自己;班级。。。。构造函数(){self=this….它不是一个静态方法。类实例的上下文将丢失。因此,如果您同时需要这两个上下文,为什么不分配一个变量-self=this。这是因为这样我将无法引用闭包外的函数。请参见代码中的(3)案例。简单。让self;class….constructor(){self=this….这不是一个静态方法。类实例的上下文将丢失。嗯,关于currentTarget,你是对的。我之前忽略了它,因为我在控制台时它的值为null。记录它,但那是因为它只在事件期间设置。谢谢你提供了这两个解决方案,我显然会使用currentTarget,但这样做很好知道返回函数的诀窍嗯,你对currentTarget的看法是对的。我之前忽略了它,因为我在console.logged时它的值为null,但那是因为它只在事件期间设置。谢谢你提供了这两种解决方案,我显然会使用currentTarget,但是知道返回函数的诀窍很好