类实例的this在addEventListener中被改变,如何向实例数组添加值?
解决类方法作为事件监听时的this指向问题
这个问题的核心是:事件监听回调的this默认指向触发事件的DOM元素,你直接把c.addValue传给addEventListener,调用时this就变成了<button>元素,自然访问不到类实例的arr属性。下面是几种实用的解决方法:
方法1:用bind绑定this到类实例
在添加事件监听时,通过bind把addValue方法的this固定为类实例c:
const c = new MyClass(); const btn = document.querySelector('button'); // 绑定this到c,返回一个新函数作为回调 btn.addEventListener('click', c.addValue.bind(c));
bind会创建一个新函数,无论这个函数怎么被调用,内部的this都会指向你传入的c,这样就能正常访问this.arr了。
方法2:用箭头函数包裹回调
箭头函数没有自己的this,它的this继承自外层作用域。用箭头函数调用c.addValue,就能确保方法内部的this指向类实例:
const c = new MyClass(); const btn = document.querySelector('button'); btn.addEventListener('click', (event) => c.addValue(event));
这里箭头函数的外层作用域是全局,我们直接通过c.addValue()调用方法,此时方法内部的this自然指向c(通过实例调用类方法时,this默认指向该实例)。
方法3:在构造函数中提前绑定this
在类的构造函数里,把addValue方法的this绑定到当前实例,这样之后无论怎么传递这个方法,this都不会改变:
class MyClass { constructor() { this.arr = []; // 提前绑定this到实例 this.addValue = this.addValue.bind(this); } addValue(event) { console.log(this); // 现在this是MyClass实例 this.arr.push('added'); console.log(this.arr); } } const c = new MyClass(); const btn = document.querySelector('button'); // 直接传方法即可,this已经绑定好 btn.addEventListener('click', c.addValue);
这种方式适合需要多次复用这个方法的场景,不用每次都手动绑定。
方法4:用类字段箭头函数定义方法
把addValue定义为类字段形式的箭头函数,箭头函数的this会词法绑定到类实例,永远不会改变:
class MyClass { constructor() { this.arr = []; } // 用箭头函数定义类方法 addValue = (event) => { console.log(this); // this是MyClass实例 this.arr.push('added'); console.log(this.arr); } } const c = new MyClass(); const btn = document.querySelector('button'); btn.addEventListener('click', c.addValue);
注意这是ES6+的语法,需要确保你的环境支持(比如现代浏览器直接运行,或用Babel转译兼容旧环境)。
内容的提问来源于stack exchange,提问作者Miu
相关产品推荐
相关产品推荐

