Самостоятельно вызывая функцию через setTimeout внутри объекта

Я хотел бы вызвать метод объекта JS в том же методе объекта через setTimeout:

var ads = {

  init: function() {
    ads.display_ads();
  },

  display_ads: function() {
     console.log('Displaying Ads');
     setTimeout('ads.display_ads()', 5000);
  }
}

Тем не менее, я получаю это сообщение об ошибке:

ads is not defined

setTimeout('ads.display_ads()', 2000);

Что мне здесь не хватает? Как бы я изменил строку в функции setTimeout?

Спасибо за вашу помощь!

Изменить: я использую Firefox на Mac.

4 ответа

Решение

Просто измените это на ads.display_adsобратите внимание, что это не String, т.е.

var ads = {
    init: function() {
        ads.display_ads();
    },
    display_ads: function() {
        console.log('Displaying Ads');
        setTimeout(ads.display_ads, 5000);
    }
}

Как @FelixKling указывает в своем комментарии ниже, будьте осторожны с тем, что this относится к в ads.display_ads, Если ads.display_ads вызывается через ads.init() или же ads.display_ads()this будет adsObject, Однако, если вызывается через setTimeoutthis будет window,

Если контекст важен, вы можете передать анонимную функцию setTimeoutкоторый в свою очередь вызывает ads.display_ads():

setTimeout(function() {
    ads.display_ads();
}, 5000);

или же

var self = this;
setTimeout(function() {
    self.display_ads();
}, 5000);

Пытаться this.display_ads,

Я бы порекомендовал вам использовать это для ссылок ads

поэтому код будет выглядеть так:

var ads = {

  init: function() {
    this.display_ads();
  },

  display_ads: function() {
     console.log('Displaying Ads');
     setTimeout(this.display_ads, 5000);
  }
}

Итак, как сказал Джейк Кларксон, ads.display_ads:

setTimeout(hitch(ads, ads.display_ads), 5000);

Разница в том, что вы должны использовать функцию "заминка":

function hitch(scope, callback) {
    return function () {
         return callback.apply(scope, Array.prototype.slice.call(arguments));
    }
}

Эта функция гарантирует, что областью обратного вызова является ваш рекламный объект. Смотрите MDN для описания функции применения:

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/apply

Ответ jabclab мне очень помог. Я пытался заставить игровой цикл работать, но кажется this ссылался window вместо объекта, который я создал. Вот минимальная версия теперь работающего кода (он просто подсчитывает каждую секунду и записывает его в div "content"):

function Game(model, renderer){
    this.model = model;
    this.renderer = renderer;
    this.run = function(){
        this.model.update();
        this.renderer.draw(this.model);
        var self = this;
        setTimeout(function(){self.run();}, 1000);
    };
}
function Model(){
    this.data = 0;
    this.update = function(){
        this.data++;
    };
}
function Renderer(){
    this.draw = function(model, interpolation){
        document.getElementById("content").innerHTML = model.data;
    };
}
var game = new Game(new Model(), new Renderer());
game.run();

Вместо setTimeout(this.run, 1000) я использовал self вместо this чтобы уточнить, какой объект имеется в виду (как предлагает jabclab). Думаю, я бы добавил это, потому что я использую конструктор объекта и немного другой синтаксис. Особенно используя ads.method не сработало (потому что Game - еще не объект), поэтому мне пришлось использовать последнее решение.

Другие вопросы по тегам