I am wondering why these code variations are behaving the way they do.
First Setup:
var a = {
val: 23,
div: null,
test: function(){
this.div.innerHTML = this.div.innerHTML + ' ' + this.val;
},
run: function(){
// why is "this" the window object here when called by requestAnimationFrame?
requestAnimationFrame(this.run);
this.test();
},
init: function(){
this.div = document.getElementById('output');
this.run();
}
};
a.init();
This one I expected to work but fails as soon as requestAnimationFrame
begins calling the run
function as this
refers to Window
when called by requestAnimationFrame
. Fiddle: http://jsfiddle.net/titansoftime/gmxourcq/
This one works:
var a = {
val: 23,
div: null,
test: function(){
this.div.innerHTML = this.div.innerHTML + ' ' + this.val;
},
run: function(){
var self = this;
requestAnimationFrame(function(){ self.run(); });
this.test();
},
init: function(){
this.div = document.getElementById('output');
this.run();
}
};
a.init();
Passing the run
function via a closure solves the problem. Why would this work and not the prior example work? My actual code needs to run extremely efficiently and I'd rather not use a closure inside my run loop as I don't want to poke the GC. Perhaps this is not a big deal? (I'm mostly worried about mobile devices). Fiddle: http://jsfiddle.net/titansoftime/Lqhcwoyu/
And finally the last case which works as expected:
var a = {
val: 23,
div: null,
test: function(){
this.div.innerHTML = this.div.innerHTML + ' ' + this.val;
},
run: function(){
requestAnimationFrame(a.run);
a.test();
},
init: function(){
this.div = document.getElementById('output');
this.run();
}
};
a.init();
Again for performance (OCD) reasons I'd rather not reference this object via global if I can avoid it. Fiddle: http://jsfiddle.net/titansoftime/5816fLxe/
Can someone please explain to me why the first example fails and also the best course to take regarding running this loop as memory/GC efficient as possible?
Thank you for your time.