Самостоятельно вызывая функцию через 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
будет ads
Object
, Однако, если вызывается через setTimeout
this
будет 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 - еще не объект), поэтому мне пришлось использовать последнее решение.