NSF
NSF

Reputation: 2549

How to pass "this" to window setInterval

Suppose I have a function a:

function a() {
    this.b = 1;
    this.set = setInterval(function() {console.log(this.b);}, 200);
}

So when a.set() is called the anonymous function will be called. But this won't work as this at that time when the function is triggered points to the window object. Also it's not a good idea to use a.b as there may be multiple instances of a.

What is a good solution to this problem?

Upvotes: 15

Views: 15626

Answers (7)

Use bind instead of saving this referance.

class Person {
    a() {
        this.b = 1;
        this.set = setInterval(function() {console.log(this.b);}, 1000);
    }

    c() {
        this.b = 1;
        this.set = setInterval((function() {console.log(this.b);}).bind(this), 1000);
    }
}

p = new Person()
p.a() //prints undefined
p.c() //prints 1

Upvotes: 2

Smily
Smily

Reputation: 3090

This question is waay too old, but I did not like the solutions in here as the idea has mostly been about attaching the instance to something public.

Here is another, working idea:

The problem is that when calling as a callback from an interval, the scope is not inside this. However, you can kinda force it to be by defining a Function variable.

function a() {
  var localCallback: () => {
    // access `this` as you will
    console.log(this);
  };
  this.timer = setInterval( localCallback, this.saveInterval );
}

Hope this is helpful!

Upvotes: 0

Jeffrey Zhao
Jeffrey Zhao

Reputation: 5023

In your case, you can simply:

function a() {
    var _this = this;
    this.b = 1;
    this.set = setInterval(function () {
      console.log(_this.b);
    }, 200);
}

Normally, we can also have a helper method Function.prototype.bind to fix the this reference.

Upvotes: 1

Lux
Lux

Reputation: 18240

Since we have ES6 now, I think we need another answer here:

Use an arrow function:

function a() {
  this.b = 1;
  this.set = setInterval(() => {console.log(this.b);}, 200);
}

Arrow functions, opposite to normal functions, don't have a this context on their own. This means you have access to the outer this.

Upvotes: 12

Dbl
Dbl

Reputation: 5904

This would be the cleanest solution, since most of the time you actually want to switch the this context for your consecutive method calls:

    // store scope reference for our delegating method
    var that = this;
    setInterval(function() {
        // this would be changed here because of method scope, 
        // but we still have a reference to that
        OURMETHODNAME.call(that);
    }, 200);

Upvotes: 6

nnnnnn
nnnnnn

Reputation: 150070

Store a reference to this:

function a() {
    var self = this;
    self.b = 1;
    self.set = setInterval(function() {console.log(self.b);}, 200);
}

The anonymous function that you pass to setInterval has access to any variables in its containing scope, i.e., any local variables of function a(). The magic of JS closures keeps these variables alive even after a() has completed, and each invocation of a() gets its own closure.

Upvotes: 26

Sirko
Sirko

Reputation: 74076

Just save your this reference in some other variable, that is not overridden by the window-call later on. Later you can use that variable to reference he object you started with.

function a() {
    this.b = 1;
    var that = this;
    this.set = setInterval(function() {console.log(that.b);}, 200);
}

Upvotes: 2

Related Questions