类初始化时this指向异常:Cannot read property 'cvs' of undefined
问题原因与解决方案
这个报错的核心是函数调用时this的指向绑定问题,咱们来拆解一下:
当你在gameLoop方法里调用window.requestAnimationFrame(this.gameLoop)时,你只是把gameLoop函数本身作为回调传递了出去。此时这个函数脱离了类实例的上下文,执行时内部的this不再指向gCont这个genGameObject实例——在严格模式下(现代JS环境默认启用),这个this就会变成undefined,自然就找不到cvs属性了。
几种可行的修复方案
1. 用箭头函数包裹回调(最简单的临时修复)
箭头函数会继承外层作用域的this,所以可以直接把回调改成箭头函数形式:
gameLoop() { this.cvs.width = 400; this.cvs.height = 400; this.ctx.fillStyle = "#64004C"; this.ctx.fillRect(0, 0, this.cvs.width, this.cvs.height); this.drawMap(); this.drawPlayer(); // 用箭头函数保留this指向 window.requestAnimationFrame(() => this.gameLoop()); }
2. 用bind()手动绑定this
你可以在传递回调时,用bind()把this强行绑定到类实例:
gameLoop() { // ... 原有代码 window.requestAnimationFrame(this.gameLoop.bind(this)); }
3. 在构造函数中提前绑定方法(更稳妥的长期方案)
如果这个方法会被多次作为回调传递,推荐在构造函数里提前绑定this,避免每次调用都重新绑定:
constructor(sel) { this.cvs = document.querySelector(sel) || canvas; this.ctx = this.cvs.getContext("2d"); this.gameState = "unStarted"; // 提前绑定gameLoop的this到当前实例 this.gameLoop = this.gameLoop.bind(this); }
4. 用类字段箭头函数定义方法(ES6+语法)
如果你使用支持类字段的JS环境,可以直接用箭头函数定义gameLoop,这样函数内部的this会自动绑定到类实例:
class genGameObject { constructor(sel) { this.cvs = document.querySelector(sel) || canvas; this.ctx = this.cvs.getContext("2d"); this.gameState = "unStarted"; } // 用箭头函数定义方法,自动绑定this gameLoop = () => { this.cvs.width = 400; this.cvs.height = 400; this.ctx.fillStyle = "#64004C"; this.ctx.fillRect(0, 0, this.cvs.width, this.cvs.height); this.drawMap(); this.drawPlayer(); window.requestAnimationFrame(this.gameLoop); } // ... 其他方法 }
额外的小提示
你的drawPlayer方法里,this.mapLoaded.player.x和y是字符串类型(来自mapArray里的"10"),画圆的时候可能会出现意外行为,建议转成数字:
this.playerX = Number(this.mapLoaded.player.x); this.playerY = Number(this.mapLoaded.player.y);
或者初始化mapArray时直接用数字:
const mapArray = { player: { x: 10, y: 10 }, coins: [ ] };
内容的提问来源于stack exchange,提问作者Ferinix
相关产品推荐
相关产品推荐

