如何不使用bind在事件处理函数中同时获取类实例和事件本身的this上下文
方案合规性说明
- 你使用函数默认参数的写法完全符合ES6语法规范,不存在语法层面的违规问题,但需要注意当前写法的逻辑隐患:函数默认参数的
this是在函数执行时绑定的,事件触发时方法的this已经被jQuery绑定为触发事件的DOM元素,因此你写的el = this实际拿到的el是DOM元素,和你注释预期的「拿到类实例this」不符。如果你本地测试符合预期,大概率是实际运行代码额外给方法绑定了类实例上下文,和你贴出的代码存在出入。 - 你贴出的示例代码还存在一个基础错误:类实例化时遗漏了
new关键字,直接写var TheTest = A_Test();会抛出调用错误,需要改成var TheTest = new A_Test();。
更稳妥的实现方案
如果你需要同时保留「事件触发DOM元素」和「类实例上下文」两个上下文,推荐两种不容易出错的实现方式:
方案1:箭头函数包裹处理逻辑
利用箭头函数的this继承外层作用域的特性,直接固定类实例上下文,主动传入事件目标:
class A_Test { constructor(a, b) { this.selector = '.foam_types'; } bind_foam_type_radios() { $(this.selector).on({ mouseenter: (e) => this.showFoamTypeExample(e, e.currentTarget), mouseleave: (e) => this.hideFoamTypeExample(e, e.currentTarget), click: (e) => this.selectFoamType(e, e.currentTarget), }, '.foam_type_option'); } showFoamTypeExample(e, targetEl) { console.log(targetEl); // 触发事件的DOM元素 console.log(this); // 类实例上下文 } }
方案2:使用jQuery事件数据参数传递类实例
利用jQuery的on方法支持传递自定义数据的特性,把类实例挂载到事件对象上:
class A_Test { constructor(a, b) { this.selector = '.foam_types'; } bind_foam_type_radios() { $(this.selector).on({ mouseenter: this.showFoamTypeExample, mouseleave: this.hideFoamTypeExample, click: this.selectFoamType, }, '.foam_type_option', {classIns: this}); // 自定义数据挂载到事件对象的data属性 } showFoamTypeExample(e) { console.log(this); // 触发事件的DOM元素 console.log(e.data.classIns); // 类实例上下文 } }
如果你要保留默认参数的写法
可以提前在构造函数中给方法绑定类实例上下文,调整默认参数的赋值逻辑即可:
class A_Test { constructor(a, b) { this.selector = '.foam_types'; // 提前绑定类实例上下文,后续方法调用的this永远指向类实例 this.showFoamTypeExample = this.showFoamTypeExample.bind(this); } bind_foam_type_radios() { $(this.selector).on({ mouseenter: this.showFoamTypeExample, mouseleave: this.hideFoamTypeExample, click: this.selectFoamType, }, '.foam_type_option'); } showFoamTypeExample(e, targetEl = e.currentTarget) { console.log(targetEl); // 触发事件的DOM元素 console.log(this); // 类实例上下文 } }
内容的提问来源于stack exchange,提问作者Jpv
相关产品推荐
相关产品推荐

