所以我用requestAnimationFrame编写了一个有效的应用程序(实际上是其中的一半)。在项目过于复杂之前,我急于以面向对象的方式重写它,这样我们就可以更好地实现插件(并且还可以在不更改整个应用程序的情况下修复模块)。事实上,该应用程序的第一个版本实际上已经搞砸了很多测试代码。
所以我有以下内容:
Aventura.prototype.update = function() {
var av = this;
requestAnimationFrame(av.update);
/* ... frame code ... */
};
我在控制台日志中的requestAnimationFrame行中收到“Uncaught TypeError:Type error”。我知道我的浏览器有一个正确的requestAnimationFrame实现,因为我完全使用了我的应用程序的混乱版本。
我得出的结论是它引发了一个异常,因为我正在调用一个方法,该方法是调用者自己的父对象的一个成员(我知道它的方法完全相同,但问题显然不在于自我...因为那是英国皇家空军应该做的事情。什么是错的线索?
答案 0 :(得分:5)
这与requestAnimationFrame
无关。这是与一般传递函数相关的基本JavaScript问题,以及this
。
人们倾向于认为对象内部的函数值属性,例如下面的myFn
var myObj = {
myFn: function() {console.log(this);}
};
某种方式myObj
“在”this
中“。错误。仅在函数调用时分配this
。如果我说myObj.myFn()
,this
变为myObj
,但我可以轻而易举地说myObj.myFn.call(otherObj)
让this
成为其他内容。
将函数作为参数传递给setTimeout
,promises或requestAnimationFrame
时,这一点很重要。只是通过myObj.myFn
传递函数,但它没有关联的this
。 requestAnimationFrame
不知道此功能的来源以及this
要调用它的内容,因此它使用this
window
或null
来调用它,或0,或undefined
,或谁知道什么。这会导致错误。
解决问题的最简单方法是简单地说
requestAnimationFrame(function() {av.update(); });
现在使用正确的update
调用this
。
更复杂,更等效的方式是
requestAnimationFrame(av.update.bind(av));
我认为你将函数本身传递给requestAnimationFrame
的方式不会很好。你本质上是建立一个递归调用链,最终堆栈将溢出。您需要将要在requestAnimationFrame
回调上执行的逻辑与逻辑分开,以请求帧。
答案 1 :(得分:0)
我最终在这里找到了另一个问题的答案。我不认为它被归类为副本,因为这两个问题都以不同的方式提出,有人可以找到一个而不是另一个问题(我自己在网上寻找类似的问题并且没有遇到过这个问题潜在的重复)。