Reputation: 644
So I have written a working application (actually half of it) with requestAnimationFrame. Before the project gets too complex I'm rushing to rewrite it in an object-oriented style so we can implement plugins better (and also fix modules without changing the whole app). In fact the first version of the app was really messed up and made up from a lot of test code.
So I have the following:
Aventura.prototype.update = function() {
var av = this;
requestAnimationFrame(av.update);
/* ... frame code ... */
};
And I get "Uncaught TypeError: Type error " in the console log, right in the requestAnimationFrame line. I know my browser has a proper requestAnimationFrame implementation since I used the messed up version of my app perfectly well.
I've reached the conclusion that it raises an exception because I'm calling a method that is a member of the caller's own parent object (I know it's exactly the same method, but the problem clearly isn't on self-calling since that's what RAF is supposed to do). Any clues of what's wrong?
Upvotes: 1
Views: 4227
Reputation:
This has nothing to do with requestAnimationFrame
. It is a basic JavaScript issue related to passing functions in general, and the meaning of this
.
People tend to think that a function-valued property inside an object, such as myFn
in the below
var myObj = {
myFn: function() {console.log(this);}
};
somehow has myObj
"baked in" as this
. Wrong. this
is assigned only at the time the function is called. If I say myObj.myFn()
, this
becomes myObj
, but I could just as easily say myObj.myFn.call(otherObj)
to have this
be something else.
This becomes important when passing functions around as parameters to setTimeout
, promises, or requestAnimationFrame
. Just passing myObj.myFn
passes the function, but it has no associated this
. requestAnimationFrame
has no idea where this function came from and what this
to call it with, so it calls it with a this
of window
, or null
, or 0, or undefined
, or who knows what. This causes the error.
The simplest way to fix the problem is to simply say
requestAnimationFrame(function() {av.update(); });
Now update
is called with the correct this
.
A more sophisticated, equivalent way, would be
requestAnimationFrame(av.update.bind(av));
I don't think the way you're passing the function itself to requestAnimationFrame
is going to work well. You're essentially setting up a chain of recursive calls, and eventually the stack will overflow. You need to separate the logic to be executed on the requestAnimationFrame
callback from the logic to request the frame.
Upvotes: 5
Reputation: 644
I've ended up finding the answer on another question here. I don't think it classifies as a duplicate though, since both questions were asked in different ways and someone could find one but not the other question (I myself seeked for a similar problem all over the web and didn't ever run into this potential duplicate).
How to call requestAnimFrame on an object method?
Upvotes: 0