//
// version 1
//
var requestAnimFram = (function(){
return window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequsetAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
}
})();
//version 1 usage
function main(){
//main loop
...
requestAnimFram(main);
}
main();
//
// version 2
//
var animFram = {
req: window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function(callback){
window.setTimeout(callback, 1000 / 60);
},
ccl: window.cancelAnimationFrame ||
window.mozCancelAnimationFrame,
myReq: 0
};
//version 2 usage
function main(){
...
aniFram.myReq = aniFram.req(main);
}
main();
function stop(){
aniFram.ccl(myReq);
}
While I was exploring some example codes, I found requestAnimationFrame. version 1 is carved from that and it works fine. After seaching for a while, I found cancelAnimationFrame as well and wanted to use both of them. So I made a dummy page for test. The version 2 is carved from it.
The problem is that, it doesn't loop. So, I have two questions.
Is it impossible to use
requestAnimationFramein this way? If so, why exactly so?If it's possible-but I'm doing it in wrong way, how can I acheive this?
This is a duplicate("Uncaught TypeError: Illegal invocation" in Chrome). But I'm still gonna answer my own question with more detail, as such could help others to understand this matter in a different way.
It is impossible.
This problem, by itself, can be easily fixed by using
call()andbind()andapply()methods.Notice the similarity in here that all 3 methods somehow have an additional parameter 'window'. They all have a same reason for it:
requestAnimationFrameis a method ofwindowobject that requires the context ofwindow.aniFramis an object. It has a methodreqwhich references thewindow.requestAnimationFrame.aniFram.req(main)invokes thewindow.requestAnimationFramein the context of theaniFram, notwindow. That's why it doesn't work. Let's consider another example code:Example Code
This is exactly same situation as your code, version 2. You invoke
obj2.hitman()that referencesobj1.hitmanexpecting to change the value ofobj1.target, but it does nothing. Because whatobj1.hitmandoes is executing a statementthis.target = 'RIP'. Since it is executed in the context ofobj2, this statement becomesobj2.target = 'RIP'. There is notargetproperty in obj2.call, apply, bind
That's where these methods kick in. Without them, Javascript Engine determines context automatically (current object. ie. aniFram, obj2). By attaching these methods to your code, now you can decide in which context it will be executed (ie. window, obj1).
This is also called as an Alias Function. (If Javascript has first-class functions, why doesn't this work?)