Reputation: 2549
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
Reputation: 612
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
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
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
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
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
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
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