面向对象编程中如何从回调函数访问类实例方法?
解决类方法在事件回调中无法访问的问题
嘿,这绝对是面向对象编程入门时最容易踩的「this指向」坑之一,别慌,咱们来拆解问题并解决它!
问题根源
你代码里的问题出在两层函数嵌套的this指向丢失:
- 在
forEach的普通函数回调里,this默认指向window(严格模式下是undefined),而不是你的Lightbox实例 - 到了
addEventListener的点击回调里,this又会自动指向触发事件的DOM元素(也就是那个image标签)
所以两层嵌套下来,你完全拿不到类实例的this,自然没法调用showLightbox()这类方法。
几种可行的解决方案
方案1:使用箭头函数(最简洁推荐)
箭头函数不会绑定自己的this,它会直接继承外层作用域的this。把你的forEach和点击回调都换成箭头函数,就能直接拿到类实例的this:
events() { this.images.forEach((image) => { image.addEventListener("click", (e) => { e.preventDefault(); this.showLightbox(); // 现在this指向Lightbox实例啦 this.populateLink(image.href); }); }); }
方案2:提前保存类实例的this到变量
在events方法里先把类的this存到一个变量(比如self或者that),之后不管内层函数的this怎么变,都能通过这个变量访问类方法:
events() { const self = this; // 保存类实例的引用 this.images.forEach(function(image) { image.addEventListener("click", function(e) { e.preventDefault(); self.showLightbox(); // 用self访问类实例的方法 self.populateLink(this.href); // 这里的this还是指向image元素,可以直接拿href }); }); }
方案3:正确使用bind()(你之前可能绑错了地方)
如果一定要用bind,需要确保把点击回调绑定到类实例的this上,或者给外层的forEach回调也绑定this:
events() { // 先把点击回调绑定到类实例 const handleClick = function(e) { e.preventDefault(); this.showLightbox(); this.populateLink(e.currentTarget.href); // 用e.currentTarget代替this拿触发元素的属性 }.bind(this); this.images.forEach(function(image) { image.addEventListener("click", handleClick); }); }
你之前尝试bind没成功,大概率是只绑定了forEach的回调,但内层点击回调的this还是指向DOM元素,这个写法能避免这个问题。
小补充
另外,你的populateLink方法里先清空src再赋值其实没必要,直接赋值新的src就可以啦:
populateLink(source) { this.lightBoxImage.src = source; }
内容的提问来源于stack exchange,提问作者Sackadelic
相关产品推荐
相关产品推荐

