解决js类定义里面绑定事件this指向问题

问题分析

最近一个js问题困扰了2小时:现在我们需要定义一个类,类里面初始化对象时会绑定事件,然后销毁方法会解绑事件,精简代码如下:(这里使用es6定义类的方式,使用原始的function思路也是一样的)

class Test {
  constructor() {
    this.width = 0;
  }
  //初始化对象时使window绑定事件resize,设置对象宽度
  init(){
    window.addEventListener("resize",this.resize);
  }
  
  //销毁方法,解绑事件
  destroy(){
    window.removeEventListener("resize",this.resize);
  }
  
  //监测window宽度变化,复值给对象的width属性
  resize(){
    console.log(this);
    this.width = document.body.clientWidth;
  }
}

//创建并初始化对象
let test = new Test;
test.init();

已知问题:根据事件绑定中,谁调用,this就指向谁,得知resize中的this其实是指向window,不能实现我们需要的效果,这个比较容易理解。
已知限制:

  • 1、在不改变this指向情况下,resize函数里面的this永远指向调用它的window
  • 2、绑定事件和解绑事件中第二个参数必须是同一个函数引用
  • 3、因为绑定事件和解绑事件中第二个参数必须是同一个函数引用,所以不能直接传参数

因为上面的3个限制,所以想了很多中方法都失败告终,最终还是必须使用bind方法改变this指向,同时存储bind方法返回的匿名函数,然后再传给事件绑定方法。

ps:js的bind方法能改变this指向,并返回一个新的匿名函数,但不会执行函数。例如:this.resize.bind(this)

解决代码

详细说明请看注释

class Test {
  constructor() {
    this.width = 0;
    this.newResize = null; //此属性用于保存bind返回的匿名函数
  }
  
  //初始化对象时使window绑定事件resize,设置对象宽度
  init(){
    //使用bind改变this指向,并保存返回的匿名函数
    this.newResize = this.resize.bind(this);
    window.addEventListener("resize",this.newResize )
  }
  
  //销毁,解绑事件
  destroy(){
    window.removeEventListener("resize",this.newResize );
  }
  
  //监测window宽度变化,复值给对象的width属性
  resize(){
    console.log(this);
    this.width = document.body.clientWidth;
  }
}

let test = new Test;
test.init();

如果解决了你的问题,点个赞 ^_^

你可能感兴趣的:(#,JS)