JavaScript中类方法绑定至其他类EventListener的问题
问题分析与解决方案
这个问题我太熟了——本质是JavaScript里的**函数上下文(this指向)**搞的鬼!
当你把this.render作为回调函数传给controls.addEventListener()时,这个函数的this绑定会丢失。事件触发时,render函数里的this不再指向ThreeJS类的实例,而是变成了undefined(严格模式下的默认行为),自然就找不到this.renderer了。
下面给你三种简单有效的解决办法,任选其一就行:
方法1:用bind()手动绑定this
在添加事件监听时,通过bind(this)把render函数的this固定为当前ThreeJS实例:
initControls(camera) { let controls = new THREE.TrackballControls(camera); console.log(this.renderer); // 这里的this是ThreeJS实例,renderer存在 // 关键修改:用bind绑定this controls.addEventListener('change', this.render.bind(this)); return controls; }
方法2:用箭头函数包裹回调
箭头函数会自动继承外层作用域的this,这里就是initControls里的ThreeJS实例:
initControls(camera) { let controls = new THREE.TrackballControls(camera); console.log(this.renderer); // 用箭头函数包裹,确保render里的this正确 controls.addEventListener('change', () => this.render()); return controls; }
方法3:在构造函数中提前绑定方法
如果这个render函数会被多处用作回调,可以在构造函数里一次性绑定好,后续直接用就行:
class ThreeJS { constructor(container) { this.renderer = this.initRenderer(container); this.camera = new THREE.PerspectiveCamera(45, this.renderer.aspectRatio, 1, 2000); // 提前绑定render的this指向 this.render = this.render.bind(this); this.controls = this.initControls(this.camera); } // ...其他方法不变... initControls(camera) { let controls = new THREE.TrackballControls(camera); console.log(this.renderer); // 现在直接传this.render就行,this已经绑定好了 controls.addEventListener('change', this.render); return controls; } }
三种方法都能解决你的TypeError问题,选哪种看你的代码习惯~
内容的提问来源于stack exchange,提问作者Prokop Hapala
相关产品推荐
相关产品推荐

