Ссылка «this» внутри setInterval / setTimeout внутри методов прототипа объекта - PullRequest
31 голосов
/ 25 октября 2011

Обычно я бы назначил альтернативную ссылку на себя, ссылаясь на это в setInterval.Возможно ли сделать что-то подобное в контексте метода-прототипа?Следующие ошибки кода.

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

Ответы [ 2 ]

65 голосов
/ 25 октября 2011

В отличие от такого языка, как Python, метод Javascript забывает, что это метод после его извлечения и передачи в другое место. Вы можете либо

Обернуть вызов метода внутри анонимной функции

Таким образом, доступ к свойству baz и его вызов происходят одновременно, что необходимо для правильной установки this внутри вызова метода.

Вам нужно будет сохранить this из внешней функции во вспомогательной переменной, поскольку внутренняя функция будет ссылаться на другой объект this.

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

Обернуть вызов метода внутри функции жирной стрелки

В реализациях Javascript, которые реализуют функции для стрелок , можно написать вышеприведенное решение в более сжатой форме, используя синтаксис жирной стрелки:

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

Анонимные функции Fat Arrow сохраняют this от окружающей функции, поэтому нет необходимости использовать трюк var that = this. Чтобы узнать, можете ли вы использовать эту функцию, обратитесь к таблице совместимости, например , этой .

Использовать функцию привязки

Последняя альтернатива - использовать функцию, такую ​​как Function.prototype.bind или эквивалент из вашей любимой библиотеки Javascript.

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

//dojo toolkit example:
setInterval( dojo.hitch(this, 'baz'), 100);
0 голосов
/ 17 мая 2014

я сделал прокси класс:)

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);
...