algi
algi

Reputation: 577

Self invoking function via setTimeout within object

I would like invoke a method of an js object within the very same object method via setTimeout:

var ads = {

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

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

However, I'm getting this error message:

ads is not defined

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

What am I missing here? How would i alter the string within the setTimeout function?

Thanks for your help!

Edit: I use firefox on mac.

Upvotes: 0

Views: 9737

Answers (4)

Skadi2k3
Skadi2k3

Reputation: 66

The answer of jabclab helped me greatly. I was trying to get a game loop to work, but it seems this was referencing window instead of the object I created. Here is a minimal version of the now running code (it just counts up each second and writes it into a 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();

Instead of setTimeout(this.run, 1000) I used self instead of this to clarify which object is meant (as suggested by jabclab). Thought I'd add this because I'm using an object constructor and has a slightly different syntax. Especially using ads.method didn't work (because Game is not an object yet I guess), so I had to use the last solution.

Upvotes: 0

SoWeLie
SoWeLie

Reputation: 1391

So, like jakeclarkson said, ads.display_ads:

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

The difference is that you should use a "hitch" function:

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

This function will ensure that the scope of the callback is your ads object. See MDN for a description of the apply function:

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

Upvotes: 0

jabclab
jabclab

Reputation: 15042

Just change it to ads.display_ads, note that this is not a String. i.e.

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

As @FelixKling points out in his comment below, be careful about what this refers to in ads.display_ads. If ads.display_ads is called via ads.init() or ads.display_ads() this will be the ads Object. However, if called via setTimeout this will be window.

If the context is important though, you can pass an anonymous function to setTimeout, which in turn calls ads.display_ads():

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

or

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

Upvotes: 1

kingpin
kingpin

Reputation: 1498

try this.display_ads,

I'd recommend you to use this for referencing ads

so the code will be like:

var ads = {

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

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

Upvotes: 0

Related Questions