web-dev-qa-db-fra.com

Référencement de "this" dans setInterval / setTimeout dans les méthodes de prototype d'objet

Normalement, j'attribuerais une référence "self" alternative en faisant référence à "this" dans setInterval. Est-il possible d'accomplir quelque chose de similaire dans le contexte d'une méthode prototype? Les erreurs de code suivantes.

function Foo() {}
Foo.prototype = {
    bar: function () {
        this.baz();
    },
    baz: function () {
        this.draw();
        requestAnimFrame(this.baz);
    }
};
33
Huck

Contrairement à un langage comme Python, une méthode Javascript oublie que c'est une méthode après l'avoir extraite et passée ailleurs. Tu peux soit

Envelopper l'appel de méthode dans une fonction anonyme

De cette façon, l'accès à la propriété baz et son appel se produisent en même temps, ce qui est nécessaire pour que this soit correctement défini dans l'appel de méthode.

Vous devrez enregistrer le this de la fonction externe dans une variable d'assistance, car la fonction interne fera référence à un objet this différent.

var that = this;
setInterval(function(){
    return that.baz();
}, 1000);

Enveloppez l'appel de méthode dans une fonction de flèche grasse

Dans les implémentations Javascript qui implémentent la fonction fonctions fléchées , il est possible d'écrire la solution ci-dessus de manière plus concise en utilisant la syntaxe de la flèche grasse:

setInterval( () => this.baz(), 1000 );

Les fonctions anonymes de la grosse flèche préservent le this de la fonction environnante, il n'est donc pas nécessaire d'utiliser le var that = this tour. Pour voir si vous pouvez utiliser cette fonctionnalité, consultez un tableau de compatibilité comme celui-ci .

Utilisez une fonction de liaison

Une dernière alternative consiste à utiliser une fonction telle que Function.prototype.bind ou un équivalent de votre bibliothèque Javascript préférée.

setInterval( this.baz.bind(this), 1000 );

//dojo toolkit example:
setInterval( dojo.hitch(this, 'baz'), 100);
66
hugomg

j'ai fait une classe proxy :)

function callback_proxy(obj, obj_method_name)
{
    instance_id = callback_proxy.instance_id++;
    callback_proxy.instances[instance_id] = obj;
    return eval('fn = function() { callback_proxy.instances['+instance_id+'].'+obj_method_name+'(); }');
}
callback_proxy.instance_id = 0;
callback_proxy.instances = new Array();

function Timer(left_time)
{
    this.left_time = left_time; //second
    this.timer_id;

    this.update = function()
    {
        this.left_time -= 1;

        if( this.left_time<=0 )
        {
            alert('fin!');
            clearInterval(this.timer_id);
            return;
        }
    }

    this.timer_id = setInterval(callback_proxy(this, 'update'), 1000);
}

new Timer(10);
0
gloryonjesus