setTimeout 后未找到对象方法

Posted

技术标签:

【中文标题】setTimeout 后未找到对象方法【英文标题】:Object Method not Found after setTimeout 【发布时间】:2013-03-14 01:41:56 【问题描述】:
LoCEngine.prototype.runGame = function() 
    // Initiate our game loop
    ctx.clearRect(0, 0, 800, 600);
    this.drawScene(this.curScene);
    if(this.gameRunning) 
            window.setTimeout(Engine.runGame, 1000 / this.framerate);
    

LoCEngine 是我一直在构建的一个实验性引擎,用于了解 html5 Canvas 游戏的来龙去脉。到目前为止一直很开心,直到我进入游戏循环。 runGame 会随着时间的推移而被调用,这会清除 Canvas 并调用 drawScene 函数。

LoCEngine 实例存储在变量 Engine 中(不确定在 setTimeout 中使用它是否是最佳实践...请告知)

它会在第一帧正确调用 this.drawScene,但在超时 (30 FPS) 时会抛出异常:

TypeError: this.drawScene is not a function

不太清楚为什么...我敢肯定这只是我没有遇到过的关于 JS 的问题。提前谢谢你。

【问题讨论】:

this 指的是我相信的窗口对象。你应该使用LocEngine.framerate 【参考方案1】:

您需要这样做才能正确调用方法:

LoCEngine.prototype.runGame = function() 
    // Initiate our game loop
    ctx.clearRect(0, 0, 800, 600);
    this.drawScene(this.curScene);
    if(this.gameRunning) 
            window.setTimeout(function() 
                Engine.runGame()
            , 1000 / this.framerate);
    

当您将Engine.runGame 传递给setTimeout() 时,它只是传递了方法引用本身,而其中的对象部分丢失了。因此,当它被setTimeout() 的内部调用时,它在this 中不再具有正确的对象引用,并且当代码尝试基于this 调用另一个方法时,它会生成您看到的错误。解决方法是使用我展示的匿名函数自己调用它。

也可以使用.bind(),它在内部为您做同样的事情。但是,旧版浏览器不支持.bind(),所以我倾向于只使用匿名函数。

【讨论】:

谢谢,这似乎已经解决了这个问题。

以上是关于setTimeout 后未找到对象方法的主要内容,如果未能解决你的问题,请参考以下文章

setTime

JavaScript异步编程的方法

python socket timeout设置

理解setTimeout()

Js:没有函数参数的setTimeOut? [复制]

关于this知识点