1

I have a JavaScript class

function MyClass() {

  MyClass.prototype.fooMethod = function () {
    // some logic goes here...
  }

  MyClass.prototype.fooMethod2 = function () {
    this.fooMethod();
  }
}

Everything works as expected when I call like this:

var m = MyClass();
m.fooMethod2();

However when I have this code called by setInterval I get an error: "Uncaught TypeError: Object [object DOMWindow] has no method 'fooMethod'"

var m = MyClass();
var intervalId = setInterval(m.fooMethod2, 100);

Is there any way I can use setInverval to call my method?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Tony Ranieri
  • 1,479
  • 1
  • 18
  • 32
  • @Alex Wayne is correct, but to help enlighten you as to why, you may want to read http://stackoverflow.com/questions/133973/how-does-this-keyword-work-within-a-javascript-object-literal – Matt Apr 12 '12 at 18:20

3 Answers3

4
setInterval(function() {
  m.fooMethod2();
}, 100);

In javascript, context (the value of this) is set by how the method is invoked. So foo.bar() will set this to foo inside the bar function.

But when you return a a reference to a function to be run by something else, context is not preserved. Check this out:

var callLater = function(fn) {
  setTimeout(function() {
    fn(); // no defined context, `this` will revert to the default: `window` 
  }, 1000);
};
callLater(foo.bar);

In this snippet, we pass a function into the callLater function. But when we invoke fn() we do it without any receiver, meaning we lose context.

So anytime function context is important, you have to pass in an anonymous function that will call the method on an object explicitly.

Alex Wayne
  • 178,991
  • 47
  • 309
  • 337
1
var m = new MyClass();
var intervalId = setInterval(function(){m.fooMethod2();}, 100);

Always use the new keyword when referencing an object, or you'll wind up with unexpected errors.

Elliot Bonneville
  • 51,872
  • 23
  • 96
  • 123
0

Pass context as parameter. Then all will works perfectly.

module.exports = {
   lobby = [],
   init: function () {
      var parent = this;
      setInterval(function () {
        ref.everySecondTick(parent);
      }, 2000);
   },
   everySecondTick: function (parent) {
        console.log(parent.lobby.length);
   }
}
Eliasz Kubala
  • 3,836
  • 1
  • 23
  • 28