Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting correct this-value in requestAnimationFrame

I have an app-object constructer that looks like this:

var app = function(loadedsettings) {

    return {
        init: function() {          
            this.loop();
        },

        loop: function() {
            this.update();
            window.requestAnimationFrame(this.loop);
        },

        update: function() {
            //loop through settings and call update on every object.
        },

        settings: [
             //array of settings objects, all with update methods. 
        ]
    };
}

Then when I do:

var theApp = app(settings);
theApp.init();

I get:

Uncaught TypeError: Object [object global] has no method 'update'

because when requestAnimationFrame is called, the this-value inside the loop function is set to window.

Does anybody know how to call requestAnimatinFrame with the 'theApp' object set as the this-value?

like image 809
acrmuui Avatar asked Dec 05 '25 10:12

acrmuui


2 Answers

You can create a bound function (with a fixed this), and pass that to requestAnimationFrame:

var app = function(loadedsettings) {

    return {
        init: function() {          
            this.loop();
        },

        loop: function() {
            this.update();
            window.requestAnimationFrame(this.loop.bind(this));
        },

        update: function() {
            //loop through settings and call update on every object.
        },

        settings: [
             //array of settings objects, all with update methods. 
        ]
    };
}

I think that a browser which supports requestAnimationFrame will also support Function.prototype.bind, but in case you come across one that doesn't, there are polyfills available.

like image 185
bfavaretto Avatar answered Dec 06 '25 22:12

bfavaretto


You need to cache a reference to this:

var app = function(loadedsettings) {
    var self = this;
    return {
        init: function() {          
            self.loop();
        },

        loop: function() {
            self.update();
            window.requestAnimationFrame(self.loop);
        },
        ** snip **
        ...
like image 21
Kenneth Avatar answered Dec 06 '25 23:12

Kenneth



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!