Установка исправьте это-значение в requestAnimationFrame


У меня есть конструктор app-object, который выглядит следующим образом:

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. 
        ]
    };
}

Затем, когда я это сделаю:

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

Я получаю:

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

Потому что при вызове requestAnimationFrame это-значение внутри функции цикла устанавливается в window.

Кто-нибудь знает, как вызвать requestAnimatinFrame с объектом 'theApp', установленным в качестве this-значения?

2 2

2 ответа:

Можно создать связанную функцию (с фиксированным this) и передать ее в 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. 
        ]
    };
}

Я думаю, что браузер, поддерживающий requestAnimationFrame, также будет поддерживать функцию.прототип.привязка, но в случае, если вы столкнетесь с тем, что этого не делает, есть доступные полифиллы.

Вам нужно кэшировать ссылку на this:

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

        loop: function() {
            self.update();
            window.requestAnimationFrame(self.loop);
        },
        ** snip **
        ...