运行setInterval时无法更新类内部对象属性的问题求助
问题原因
报错的核心是setInterval回调里的this指向错误:
- 你给
setInterval传入的是普通匿名函数,普通函数的this是运行时动态绑定的,在定时器回调执行时,this默认指向全局对象(浏览器环境为window,Node环境为globalThis) - 全局对象上不存在
_keys属性,所以this._keys取值为undefined,尝试给undefined设置forward属性就抛出了对应的错误。
原来写在_Init方法顶层的判断逻辑没有报错,是因为顶层代码的this指向类实例本身,能正常访问到this._keys。
解决方案
下面提供3种可直接落地的修复方式:
方案1:使用箭头函数作为回调(最简洁推荐)
箭头函数不会创建自己的this,会继承定义位置外层上下文的this,刚好可以拿到类实例的指向:
// 把原来的setInterval普通函数改成箭头函数即可 setInterval(() => { if (currentKeylogW == '"w"') { this._keys.forward = true; } else if (currentKeylogA == '"a"') { this._keys.left = true; } else if (currentKeylogD == '"d"') { this._keys.left = true; } else if (currentKeylogS == '"s"') { this._keys.right = true; } else if (currentKeylogW == '"!w"') { this._keys.forward = false; } else if (currentKeylogA == '"!a"') { this._keys.left = false; } else if (currentKeylogD == '"!d"') { this._keys.left = false; } else if (currentKeylogS == '"!s"') { this._keys.right = false; } }, 500)
方案2:提前缓存this指向
在定时器外把类实例的this存到临时变量中,回调里直接用临时变量访问实例属性:
// 在setInterval前加一行缓存this const _this = this; setInterval(function() { // 所有this换成_this即可 if (currentKeylogW == '"w"') { _this._keys.forward = true; } else if (currentKeylogA == '"a"') { _this._keys.left = true; } else if (currentKeylogD == '"d"') { _this._keys.left = true; } else if (currentKeylogS == '"s"') { _this._keys.right = true; } else if (currentKeylogW == '"!w"') { _this._keys.forward = false; } else if (currentKeylogA == '"!a"') { _this._keys.left = false; } else if (currentKeylogD == '"!d"') { _this._keys.left = false; } else if (currentKeylogS == '"!s"') { _this._keys.right = false; } }, 500)
方案3:用bind绑定this指向
通过bind方法强制把回调函数的this绑定为当前类实例:
setInterval(function() { // 内部逻辑完全不用改 if (currentKeylogW == '"w"') { this._keys.forward = true; } else if (currentKeylogA == '"a"') { this._keys.left = true; } else if (currentKeylogD == '"d"') { this._keys.left = true; } else if (currentKeylogS == '"s"') { this._keys.right = true; } else if (currentKeylogW == '"!w"') { this._keys.forward = false; } else if (currentKeylogA == '"!a"') { this._keys.left = false; } else if (currentKeylogD == '"!d"') { this._keys.left = false; } else if (currentKeylogS == '"!s"') { this._keys.right = false; } }.bind(this), 500) // 末尾加.bind(this)绑定上下文
可选优化建议
你当前的多分支if else判断可以简化,后续维护更方便:
setInterval(() => { this._keys.forward = currentKeylogW === '"w"'; this._keys.left = currentKeylogA === '"a"' || currentKeylogD === '"d"'; this._keys.right = currentKeylogS === '"s"'; }, 500)
内容的提问来源于stack exchange,提问作者seriously
相关产品推荐
相关产品推荐

