问一个ES5的this问题

silent_missile 2019-04-01 05:01:46
ES5提供了class,所以正常情况下class里面的this都是指对象实例,但是如果class内部包含一个DOM节点,这个DOM节点调用了addEventListener和removeEventListener,但是在addEventListener和removeEventListener内部this就已经指向了DOM节点,而不是class对象实例

下面的代码是一个拖拽操作的典型代码

class demo{
constructor(dom){
this.dom = dom
this.downMsg= 'mousedown'
this.moveMsg = 'mousemove'
this.upMsg = 'mouseup'
this.outEvent = {type: 'outevent'}
this.dom.addEventListener('mousedown', this.onMouseDown, false)
}
onMouseDown(event){
console.log(this.downMsg) // 这里会出错,this已经指向dom节点,而非class对象实例,所以this.downMsg是undefined
console.log(event.pageX, event.pageY)
// 下面两行绑定时没问题,调用时会出错,调用时this已经指向dom节点,而非class对象实例,所以this.onMouseMove和this.onMouseUp是undefined
this.dom.addEventListener('mousemove', this.onMouseMove, false)
this.dom.addEventListener('mouseup', this.onMouseUp, false)
}
onMouseMove(event){
console.log(this.moveMsg) // 这里会出错,调用时this已经指向dom节点,而非class对象实例,所以this.moveMsg是undefined
console.log(event.pageX, event.pageY)
document.dispatchEvent(this.outEvent) // 这里会出错,调用时this已经指向dom节点,而非class对象实例,所以this.outEvent是undefined
}
onMouseUp(event){
console.log(this.upMsg) // 这里会出错,调用时this已经指向dom节点,而非class对象实例,所以this.upMsg是undefined
// 下面两句解绑时没有问题,但是运行时有问题,因为运行时this已经指向dom节点,而非class对象实例,所以this.onMouseMove和this.onMouseUp是undefined,而不是一开始绑定的那两个函数
this.dom.removeEventListener('mousemove', this.onMouseMove)
this.dom.removeEventListener('mouseup', this.onMouseUp)
}



我尝试了一下,在addEventListener中可以使用bind

this.dom.addEventListener('mousemove', this.onMouseMove.bind(this), false) 
this.dom.addEventListener('mouseup', this.onMouseUp.bind(this), false)


这样的话,是可以运行的,但是拖拽完成后,将事件监听器解绑时会出错

this.dom.removeEventListener('mousemove', this.onMouseMove.bind(this))  // this.onMouseMove.bind(this)不是当初绑定的那个函数
this.dom.removeEventListener('mouseup', this.onMouseUp.bind(this)) // this.onMouseUp.bind(this)不是当初绑定的那个函数


从实践的角度来讲,可以在类中设一个标志位,根据它来决定是否执行onMouseMove和onMouseUp函数,也就是不解绑,但是这毕竟要增大计算量,本来拖拽就是很耗计算资源的,而且这么做也有点不伦不类

在老式JavaScript中,可以先用一个_this把this存起来,然后再用_this来完成计算,可是在ES5中,我试了一下不行,至少在constructor构造函数中不行

这里请教大佬,谁能帮我解决一下这个this指针的问题,不胜感激
...全文
89 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
silent_missile 2019-04-01
  • 打赏
  • 举报
回复
多谢指点,受其启发,我又发现了一种方法,箭头函数
moveEvent = (event)=>{code}

这样也可以保证this指向class实例对象不变

bind和箭头函数都必须在构造函数constructor内定义,不能用成员函数的方式定义
天际的海浪 2019-04-01
  • 打赏
  • 举报
回复
因为每次执行bind()都是返回一个新的函数,你事件绑定的函数和解绑的函数就不是同一个函数了。 要用一个变量保存bind()返回的函数,事件绑定和解绑时都用这个变量。 moveEvent = this.onMouseMove.bind(this); this.dom.addEventListener('mousemove', moveEvent, false) this.dom.removeEventListener('mousemove', moveEvent)

87,923

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧