JavaScript类内方向标识布尔属性为何在事件监听与rAF回调中变为undefined?
核心问题根源:
this 上下文绑定丢失 你在构造器里定义的rightInput/leftInput/upInput这些布尔属性从来没有无故变成undefined,从实例创建完成开始,它们就一直挂在player这个Character实例上,所有读取异常全是因为方法被独立调用时,内部的this没有指向对应的player实例。
具体两个出错的位置:
requestAnimationFrame(player.update)调用时的this指向错误
你把player.update方法的引用直接传给RAF后,RAF执行这个函数时,不会把函数内部的this自动绑定到player实例上,非严格模式下this会指向全局window对象,严格模式下this直接是undefined。这时候在update方法里访问this.rightInput,读取的根本不是player实例上的属性,自然会拿到undefined触发报错。- 事件监听器绑定
player.charMovements时的this指向错误
浏览器触发事件回调时,会把回调函数内部的this自动绑定到事件源(这里就是window对象),不会保留你当初绑定的player实例上下文。所以你在charMovements里写的this.rightInput = true,本质是给window对象新增了一个同名属性,完全没有修改到player实例上的输入状态值。你在回调里打日志看到的属性值,也是window对象上的初始属性(也就是undefined),才会产生“构造器里的属性突然丢了”的错觉。
可行的修复方案
- 给方法手动绑定固定的this指向
传递方法引用给RAF、事件监听器时,用bind把方法的this永久锚定到player实例上:// 锚定update的this requestAnimationFrame(player.update.bind(player)); // 锚定键盘回调的this window.addEventListener('keydown', player.charMovements.bind(player)); window.addEventListener('keyup', player.charMovements.bind(player)); - 在构造函数中提前绑定方法this,从源头避免上下文漂移
在Character类的constructor末尾追加绑定逻辑,让实例方法从创建完成开始,this就永远指向当前实例:constructor(/* 原有参数和属性定义保持不变 */) { // 原有属性赋值逻辑... this.charMovements = this.charMovements.bind(this); this.update = this.update.bind(this); } - 用箭头函数定义类实例方法
箭头函数没有独立的this作用域,会自动继承定义时所在的类实例上下文,是前端开发里处理这类问题最常用的写法,直接把原有的类方法改成箭头函数形式即可,不需要额外写bind逻辑:class Character { constructor(/* 原有参数和属性定义保持不变 */) { // 原有属性赋值逻辑... } // 箭头函数形式的方法,this自动绑定当前实例 charMovements = (e) => { // 原有键盘判断逻辑完全不需要修改 } update = () => { // 原有移动逻辑完全不需要修改 } }
额外注意的小问题
你创建player实例时传入的groundLevel变量在现有代码里没有定义,运行时会触发ReferenceError,记得提前把这个变量声明成你设定的地面基准Y轴坐标值即可,这个问题和this绑定的问题无关。
内容的提问来源于stack exchange,提问作者Marctherealtwin
相关产品推荐
相关产品推荐

